1 /*
2  * Copyright (C) 2014 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 com.android.internal.util.ArrayUtils;
20 
21 import java.util.Arrays;
22 import libcore.util.EmptyArray;
23 
24 /**
25  * Implements a growing array of int primitives.
26  *
27  * @hide
28  */
29 public class IntArray implements Cloneable {
30     private static final int MIN_CAPACITY_INCREMENT = 12;
31 
32     private int[] mValues;
33     private int mSize;
34 
35     /**
36      * Creates an empty IntArray with the default initial capacity.
37      */
IntArray()38     public IntArray() {
39         this(10);
40     }
41 
42     /**
43      * Creates an empty IntArray with the specified initial capacity.
44      */
IntArray(int initialCapacity)45     public IntArray(int initialCapacity) {
46         if (initialCapacity == 0) {
47             mValues = EmptyArray.INT;
48         } else {
49             mValues = ArrayUtils.newUnpaddedIntArray(initialCapacity);
50         }
51         mSize = 0;
52     }
53 
54     /**
55      * Appends the specified value to the end of this array.
56      */
add(int value)57     public void add(int value) {
58         add(mSize, value);
59     }
60 
61     /**
62      * Inserts a value at the specified position in this array.
63      *
64      * @throws IndexOutOfBoundsException when index < 0 || index > size()
65      */
add(int index, int value)66     public void add(int index, int value) {
67         if (index < 0 || index > mSize) {
68             throw new IndexOutOfBoundsException();
69         }
70 
71         ensureCapacity(1);
72 
73         if (mSize - index != 0) {
74             System.arraycopy(mValues, index, mValues, index + 1, mSize - index);
75         }
76 
77         mValues[index] = value;
78         mSize++;
79     }
80 
81     /**
82      * Searches the array for the specified value using the binary search algorithm. The array must
83      * be sorted (as by the {@link Arrays#sort(int[], int, int)} method) prior to making this call.
84      * If it is not sorted, the results are undefined. If the range contains multiple elements with
85      * the specified value, there is no guarantee which one will be found.
86      *
87      * @param value The value to search for.
88      * @return index of the search key, if it is contained in the array; otherwise, <i>(-(insertion
89      *         point) - 1)</i>. The insertion point is defined as the point at which the key would
90      *         be inserted into the array: the index of the first element greater than the key, or
91      *         {@link #size()} if all elements in the array are less than the specified key.
92      *         Note that this guarantees that the return value will be >= 0 if and only if the key
93      *         is found.
94      */
binarySearch(int value)95     public int binarySearch(int value) {
96         return ContainerHelpers.binarySearch(mValues, mSize, value);
97     }
98 
99     /**
100      * Adds the values in the specified array to this array.
101      */
addAll(IntArray values)102     public void addAll(IntArray values) {
103         final int count = values.mSize;
104         ensureCapacity(count);
105 
106         System.arraycopy(values.mValues, 0, mValues, mSize, count);
107         mSize += count;
108     }
109 
110     /**
111      * Ensures capacity to append at least <code>count</code> values.
112      */
ensureCapacity(int count)113     private void ensureCapacity(int count) {
114         final int currentSize = mSize;
115         final int minCapacity = currentSize + count;
116         if (minCapacity >= mValues.length) {
117             final int targetCap = currentSize + (currentSize < (MIN_CAPACITY_INCREMENT / 2) ?
118                     MIN_CAPACITY_INCREMENT : currentSize >> 1);
119             final int newCapacity = targetCap > minCapacity ? targetCap : minCapacity;
120             final int[] newValues = ArrayUtils.newUnpaddedIntArray(newCapacity);
121             System.arraycopy(mValues, 0, newValues, 0, currentSize);
122             mValues = newValues;
123         }
124     }
125 
126     /**
127      * Removes all values from this array.
128      */
clear()129     public void clear() {
130         mSize = 0;
131     }
132 
133     @Override
clone()134     public IntArray clone() throws CloneNotSupportedException {
135         final IntArray clone = (IntArray) super.clone();
136         clone.mValues = mValues.clone();
137         return clone;
138     }
139 
140     /**
141      * Returns the value at the specified position in this array.
142      */
get(int index)143     public int get(int index) {
144         if (index >= mSize) {
145             throw new ArrayIndexOutOfBoundsException(mSize, index);
146         }
147         return mValues[index];
148     }
149 
150     /**
151      * Returns the index of the first occurrence of the specified value in this
152      * array, or -1 if this array does not contain the value.
153      */
indexOf(int value)154     public int indexOf(int value) {
155         final int n = mSize;
156         for (int i = 0; i < n; i++) {
157             if (mValues[i] == value) {
158                 return i;
159             }
160         }
161         return -1;
162     }
163 
164     /**
165      * Removes the value at the specified index from this array.
166      */
remove(int index)167     public void remove(int index) {
168         if (index >= mSize) {
169             throw new ArrayIndexOutOfBoundsException(mSize, index);
170         }
171         System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1);
172         mSize--;
173     }
174 
175     /**
176      * Returns the number of values in this array.
177      */
size()178     public int size() {
179         return mSize;
180     }
181 
182     /**
183      * Returns a new array with the contents of this IntArray.
184      */
toArray()185     public int[] toArray() {
186         return Arrays.copyOf(mValues, mSize);
187     }
188 }
189