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