Home | History | Annotate | Download | only in text
      1 /*
      2  * Copyright (C) 2017 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.text;
     18 
     19 import android.annotation.IntRange;
     20 import android.annotation.NonNull;
     21 
     22 import com.android.internal.util.ArrayUtils;
     23 
     24 import libcore.util.EmptyArray;
     25 
     26 /**
     27  * Implements a growing array of int primitives.
     28  *
     29  * These arrays are NOT thread safe.
     30  *
     31  * @hide
     32  */
     33 public final class AutoGrowArray {
     34     private static final int MIN_CAPACITY_INCREMENT = 12;
     35     private static final int MAX_CAPACITY_TO_BE_KEPT = 10000;
     36 
     37     /**
     38      * Returns next capacity size.
     39      *
     40      * The returned capacity is larger than requested capacity.
     41      */
     42     private static int computeNewCapacity(int currentSize, int requested) {
     43         final int targetCapacity = currentSize + (currentSize < (MIN_CAPACITY_INCREMENT / 2)
     44                 ?  MIN_CAPACITY_INCREMENT : currentSize >> 1);
     45         return targetCapacity > requested ? targetCapacity : requested;
     46     }
     47 
     48     /**
     49      * An auto growing byte array.
     50      */
     51     public static class ByteArray {
     52 
     53         private @NonNull byte[] mValues;
     54         private @IntRange(from = 0) int mSize;
     55 
     56         /**
     57          * Creates an empty ByteArray with the default initial capacity.
     58          */
     59         public ByteArray() {
     60             this(10);
     61         }
     62 
     63         /**
     64          * Creates an empty ByteArray with the specified initial capacity.
     65          */
     66         public ByteArray(@IntRange(from = 0) int initialCapacity) {
     67             if (initialCapacity == 0) {
     68                 mValues = EmptyArray.BYTE;
     69             } else {
     70                 mValues = ArrayUtils.newUnpaddedByteArray(initialCapacity);
     71             }
     72             mSize = 0;
     73         }
     74 
     75         /**
     76          * Changes the size of this ByteArray. If this ByteArray is shrinked, the backing array
     77          * capacity is unchanged.
     78          */
     79         public void resize(@IntRange(from = 0) int newSize) {
     80             if (newSize > mValues.length) {
     81                 ensureCapacity(newSize - mSize);
     82             }
     83             mSize = newSize;
     84         }
     85 
     86         /**
     87          * Appends the specified value to the end of this array.
     88          */
     89         public void append(byte value) {
     90             ensureCapacity(1);
     91             mValues[mSize++] = value;
     92         }
     93 
     94         /**
     95          * Ensures capacity to append at least <code>count</code> values.
     96          */
     97         private void ensureCapacity(@IntRange int count) {
     98             final int requestedSize = mSize + count;
     99             if (requestedSize >= mValues.length) {
    100                 final int newCapacity = computeNewCapacity(mSize, requestedSize);
    101                 final byte[] newValues = ArrayUtils.newUnpaddedByteArray(newCapacity);
    102                 System.arraycopy(mValues, 0, newValues, 0, mSize);
    103                 mValues = newValues;
    104             }
    105         }
    106 
    107         /**
    108          * Removes all values from this array.
    109          */
    110         public void clear() {
    111             mSize = 0;
    112         }
    113 
    114         /**
    115          * Removes all values from this array and release the internal array object if it is too
    116          * large.
    117          */
    118         public void clearWithReleasingLargeArray() {
    119             clear();
    120             if (mValues.length > MAX_CAPACITY_TO_BE_KEPT) {
    121                 mValues = EmptyArray.BYTE;
    122             }
    123         }
    124 
    125         /**
    126          * Returns the value at the specified position in this array.
    127          */
    128         public byte get(@IntRange(from = 0) int index) {
    129             return mValues[index];
    130         }
    131 
    132         /**
    133          * Sets the value at the specified position in this array.
    134          */
    135         public void set(@IntRange(from = 0) int index, byte value) {
    136             mValues[index] = value;
    137         }
    138 
    139         /**
    140          * Returns the number of values in this array.
    141          */
    142         public @IntRange(from = 0) int size() {
    143             return mSize;
    144         }
    145 
    146         /**
    147          * Returns internal raw array.
    148          *
    149          * Note that this array may have larger size than you requested.
    150          * Use size() instead for getting the actual array size.
    151          */
    152         public @NonNull byte[] getRawArray() {
    153             return mValues;
    154         }
    155     }
    156 
    157     /**
    158      * An auto growing int array.
    159      */
    160     public static class IntArray {
    161 
    162         private @NonNull int[] mValues;
    163         private @IntRange(from = 0) int mSize;
    164 
    165         /**
    166          * Creates an empty IntArray with the default initial capacity.
    167          */
    168         public IntArray() {
    169             this(10);
    170         }
    171 
    172         /**
    173          * Creates an empty IntArray with the specified initial capacity.
    174          */
    175         public IntArray(@IntRange(from = 0) int initialCapacity) {
    176             if (initialCapacity == 0) {
    177                 mValues = EmptyArray.INT;
    178             } else {
    179                 mValues = ArrayUtils.newUnpaddedIntArray(initialCapacity);
    180             }
    181             mSize = 0;
    182         }
    183 
    184         /**
    185          * Changes the size of this IntArray. If this IntArray is shrinked, the backing array
    186          * capacity is unchanged.
    187          */
    188         public void resize(@IntRange(from = 0) int newSize) {
    189             if (newSize > mValues.length) {
    190                 ensureCapacity(newSize - mSize);
    191             }
    192             mSize = newSize;
    193         }
    194 
    195         /**
    196          * Appends the specified value to the end of this array.
    197          */
    198         public void append(int value) {
    199             ensureCapacity(1);
    200             mValues[mSize++] = value;
    201         }
    202 
    203         /**
    204          * Ensures capacity to append at least <code>count</code> values.
    205          */
    206         private void ensureCapacity(@IntRange(from = 0) int count) {
    207             final int requestedSize = mSize + count;
    208             if (requestedSize >= mValues.length) {
    209                 final int newCapacity = computeNewCapacity(mSize, requestedSize);
    210                 final int[] newValues = ArrayUtils.newUnpaddedIntArray(newCapacity);
    211                 System.arraycopy(mValues, 0, newValues, 0, mSize);
    212                 mValues = newValues;
    213             }
    214         }
    215 
    216         /**
    217          * Removes all values from this array.
    218          */
    219         public void clear() {
    220             mSize = 0;
    221         }
    222 
    223         /**
    224          * Removes all values from this array and release the internal array object if it is too
    225          * large.
    226          */
    227         public void clearWithReleasingLargeArray() {
    228             clear();
    229             if (mValues.length > MAX_CAPACITY_TO_BE_KEPT) {
    230                 mValues = EmptyArray.INT;
    231             }
    232         }
    233 
    234         /**
    235          * Returns the value at the specified position in this array.
    236          */
    237         public int get(@IntRange(from = 0) int index) {
    238             return mValues[index];
    239         }
    240 
    241         /**
    242          * Sets the value at the specified position in this array.
    243          */
    244         public void set(@IntRange(from = 0) int index, int value) {
    245             mValues[index] = value;
    246         }
    247 
    248         /**
    249          * Returns the number of values in this array.
    250          */
    251         public @IntRange(from = 0) int size() {
    252             return mSize;
    253         }
    254 
    255         /**
    256          * Returns internal raw array.
    257          *
    258          * Note that this array may have larger size than you requested.
    259          * Use size() instead for getting the actual array size.
    260          */
    261         public @NonNull int[] getRawArray() {
    262             return mValues;
    263         }
    264     }
    265 
    266     /**
    267      * An auto growing float array.
    268      */
    269     public static class FloatArray {
    270 
    271         private @NonNull float[] mValues;
    272         private @IntRange(from = 0) int mSize;
    273 
    274         /**
    275          * Creates an empty FloatArray with the default initial capacity.
    276          */
    277         public FloatArray() {
    278             this(10);
    279         }
    280 
    281         /**
    282          * Creates an empty FloatArray with the specified initial capacity.
    283          */
    284         public FloatArray(@IntRange(from = 0) int initialCapacity) {
    285             if (initialCapacity == 0) {
    286                 mValues = EmptyArray.FLOAT;
    287             } else {
    288                 mValues = ArrayUtils.newUnpaddedFloatArray(initialCapacity);
    289             }
    290             mSize = 0;
    291         }
    292 
    293         /**
    294          * Changes the size of this FloatArray. If this FloatArray is shrinked, the backing array
    295          * capacity is unchanged.
    296          */
    297         public void resize(@IntRange(from = 0) int newSize) {
    298             if (newSize > mValues.length) {
    299                 ensureCapacity(newSize - mSize);
    300             }
    301             mSize = newSize;
    302         }
    303 
    304         /**
    305          * Appends the specified value to the end of this array.
    306          */
    307         public void append(float value) {
    308             ensureCapacity(1);
    309             mValues[mSize++] = value;
    310         }
    311 
    312         /**
    313          * Ensures capacity to append at least <code>count</code> values.
    314          */
    315         private void ensureCapacity(int count) {
    316             final int requestedSize = mSize + count;
    317             if (requestedSize >= mValues.length) {
    318                 final int newCapacity = computeNewCapacity(mSize, requestedSize);
    319                 final float[] newValues = ArrayUtils.newUnpaddedFloatArray(newCapacity);
    320                 System.arraycopy(mValues, 0, newValues, 0, mSize);
    321                 mValues = newValues;
    322             }
    323         }
    324 
    325         /**
    326          * Removes all values from this array.
    327          */
    328         public void clear() {
    329             mSize = 0;
    330         }
    331 
    332         /**
    333          * Removes all values from this array and release the internal array object if it is too
    334          * large.
    335          */
    336         public void clearWithReleasingLargeArray() {
    337             clear();
    338             if (mValues.length > MAX_CAPACITY_TO_BE_KEPT) {
    339                 mValues = EmptyArray.FLOAT;
    340             }
    341         }
    342 
    343         /**
    344          * Returns the value at the specified position in this array.
    345          */
    346         public float get(@IntRange(from = 0) int index) {
    347             return mValues[index];
    348         }
    349 
    350         /**
    351          * Sets the value at the specified position in this array.
    352          */
    353         public void set(@IntRange(from = 0) int index, float value) {
    354             mValues[index] = value;
    355         }
    356 
    357         /**
    358          * Returns the number of values in this array.
    359          */
    360         public @IntRange(from = 0) int size() {
    361             return mSize;
    362         }
    363 
    364         /**
    365          * Returns internal raw array.
    366          *
    367          * Note that this array may have larger size than you requested.
    368          * Use size() instead for getting the actual array size.
    369          */
    370         public @NonNull float[] getRawArray() {
    371             return mValues;
    372         }
    373     }
    374 }
    375