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
17package android.util;
18
19import com.android.internal.util.ArrayUtils;
20import libcore.util.EmptyArray;
21
22/**
23 * Implements a growing array of long primitives.
24 *
25 * @hide
26 */
27public class LongArray implements Cloneable {
28    private static final int MIN_CAPACITY_INCREMENT = 12;
29
30    private long[] mValues;
31    private int mSize;
32
33    /**
34     * Creates an empty LongArray with the default initial capacity.
35     */
36    public LongArray() {
37        this(10);
38    }
39
40    /**
41     * Creates an empty LongArray with the specified initial capacity.
42     */
43    public LongArray(int initialCapacity) {
44        if (initialCapacity == 0) {
45            mValues = EmptyArray.LONG;
46        } else {
47            mValues = ArrayUtils.newUnpaddedLongArray(initialCapacity);
48        }
49        mSize = 0;
50    }
51
52    /**
53     * Appends the specified value to the end of this array.
54     */
55    public void add(long value) {
56        add(mSize, value);
57    }
58
59    /**
60     * Inserts a value at the specified position in this array.
61     *
62     * @throws IndexOutOfBoundsException when index < 0 || index > size()
63     */
64    public void add(int index, long value) {
65        if (index < 0 || index > mSize) {
66            throw new IndexOutOfBoundsException();
67        }
68
69        ensureCapacity(1);
70
71        if (mSize - index != 0) {
72            System.arraycopy(mValues, index, mValues, index + 1, mSize - index);
73        }
74
75        mValues[index] = value;
76        mSize++;
77    }
78
79    /**
80     * Adds the values in the specified array to this array.
81     */
82    public void addAll(LongArray values) {
83        final int count = values.mSize;
84        ensureCapacity(count);
85
86        System.arraycopy(values.mValues, 0, mValues, mSize, count);
87        mSize += count;
88    }
89
90    /**
91     * Ensures capacity to append at least <code>count</code> values.
92     */
93    private void ensureCapacity(int count) {
94        final int currentSize = mSize;
95        final int minCapacity = currentSize + count;
96        if (minCapacity >= mValues.length) {
97            final int targetCap = currentSize + (currentSize < (MIN_CAPACITY_INCREMENT / 2) ?
98                    MIN_CAPACITY_INCREMENT : currentSize >> 1);
99            final int newCapacity = targetCap > minCapacity ? targetCap : minCapacity;
100            final long[] newValues = ArrayUtils.newUnpaddedLongArray(newCapacity);
101            System.arraycopy(mValues, 0, newValues, 0, currentSize);
102            mValues = newValues;
103        }
104    }
105
106    /**
107     * Removes all values from this array.
108     */
109    public void clear() {
110        mSize = 0;
111    }
112
113    @Override
114    public LongArray clone() {
115        LongArray clone = null;
116        try {
117            clone = (LongArray) super.clone();
118            clone.mValues = mValues.clone();
119        } catch (CloneNotSupportedException cnse) {
120            /* ignore */
121        }
122        return clone;
123    }
124
125    /**
126     * Returns the value at the specified position in this array.
127     */
128    public long get(int index) {
129        if (index >= mSize) {
130            throw new ArrayIndexOutOfBoundsException(mSize, index);
131        }
132        return mValues[index];
133    }
134
135    /**
136     * Returns the index of the first occurrence of the specified value in this
137     * array, or -1 if this array does not contain the value.
138     */
139    public int indexOf(long value) {
140        final int n = mSize;
141        for (int i = 0; i < n; i++) {
142            if (mValues[i] == value) {
143                return i;
144            }
145        }
146        return -1;
147    }
148
149    /**
150     * Removes the value at the specified index from this array.
151     */
152    public void remove(int index) {
153        if (index >= mSize) {
154            throw new ArrayIndexOutOfBoundsException(mSize, index);
155        }
156        System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1);
157        mSize--;
158    }
159
160    /**
161     * Returns the number of values in this array.
162     */
163    public int size() {
164        return mSize;
165    }
166}
167