1 /*
2  * Copyright (C) 2012 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 com.android.inputmethod.latin.utils;
18 
19 import java.util.Arrays;
20 
21 // TODO: This class is not thread-safe.
22 public final class ResizableIntArray {
23     private int[] mArray;
24     private int mLength;
25 
ResizableIntArray(final int capacity)26     public ResizableIntArray(final int capacity) {
27         reset(capacity);
28     }
29 
get(final int index)30     public int get(final int index) {
31         if (index < mLength) {
32             return mArray[index];
33         }
34         throw new ArrayIndexOutOfBoundsException("length=" + mLength + "; index=" + index);
35     }
36 
addAt(final int index, final int val)37     public void addAt(final int index, final int val) {
38         if (index < mLength) {
39             mArray[index] = val;
40         } else {
41             mLength = index;
42             add(val);
43         }
44     }
45 
add(final int val)46     public void add(final int val) {
47         final int currentLength = mLength;
48         ensureCapacity(currentLength + 1);
49         mArray[currentLength] = val;
50         mLength = currentLength + 1;
51     }
52 
53     /**
54      * Calculate the new capacity of {@code mArray}.
55      * @param minimumCapacity the minimum capacity that the {@code mArray} should have.
56      * @return the new capacity that the {@code mArray} should have. Returns zero when there is no
57      * need to expand {@code mArray}.
58      */
calculateCapacity(final int minimumCapacity)59     private int calculateCapacity(final int minimumCapacity) {
60         final int currentCapcity = mArray.length;
61         if (currentCapcity < minimumCapacity) {
62             final int nextCapacity = currentCapcity * 2;
63             // The following is the same as return Math.max(minimumCapacity, nextCapacity);
64             return minimumCapacity > nextCapacity ? minimumCapacity : nextCapacity;
65         }
66         return 0;
67     }
68 
ensureCapacity(final int minimumCapacity)69     private void ensureCapacity(final int minimumCapacity) {
70         final int newCapacity = calculateCapacity(minimumCapacity);
71         if (newCapacity > 0) {
72             // TODO: Implement primitive array pool.
73             mArray = Arrays.copyOf(mArray, newCapacity);
74         }
75     }
76 
getLength()77     public int getLength() {
78         return mLength;
79     }
80 
setLength(final int newLength)81     public void setLength(final int newLength) {
82         ensureCapacity(newLength);
83         mLength = newLength;
84     }
85 
reset(final int capacity)86     public void reset(final int capacity) {
87         // TODO: Implement primitive array pool.
88         mArray = new int[capacity];
89         mLength = 0;
90     }
91 
getPrimitiveArray()92     public int[] getPrimitiveArray() {
93         return mArray;
94     }
95 
set(final ResizableIntArray ip)96     public void set(final ResizableIntArray ip) {
97         // TODO: Implement primitive array pool.
98         mArray = ip.mArray;
99         mLength = ip.mLength;
100     }
101 
copy(final ResizableIntArray ip)102     public void copy(final ResizableIntArray ip) {
103         final int newCapacity = calculateCapacity(ip.mLength);
104         if (newCapacity > 0) {
105             // TODO: Implement primitive array pool.
106             mArray = new int[newCapacity];
107         }
108         System.arraycopy(ip.mArray, 0, mArray, 0, ip.mLength);
109         mLength = ip.mLength;
110     }
111 
append(final ResizableIntArray src, final int startPos, final int length)112     public void append(final ResizableIntArray src, final int startPos, final int length) {
113         if (length == 0) {
114             return;
115         }
116         final int currentLength = mLength;
117         final int newLength = currentLength + length;
118         ensureCapacity(newLength);
119         System.arraycopy(src.mArray, startPos, mArray, currentLength, length);
120         mLength = newLength;
121     }
122 
fill(final int value, final int startPos, final int length)123     public void fill(final int value, final int startPos, final int length) {
124         if (startPos < 0 || length < 0) {
125             throw new IllegalArgumentException("startPos=" + startPos + "; length=" + length);
126         }
127         final int endPos = startPos + length;
128         ensureCapacity(endPos);
129         Arrays.fill(mArray, startPos, endPos, value);
130         if (mLength < endPos) {
131             mLength = endPos;
132         }
133     }
134 
135     /**
136      * Shift to the left by elementCount, discarding elementCount pointers at the start.
137      * @param elementCount how many elements to shift.
138      */
shift(final int elementCount)139     public void shift(final int elementCount) {
140         System.arraycopy(mArray, elementCount, mArray, 0, mLength - elementCount);
141         mLength -= elementCount;
142     }
143 
144     @Override
toString()145     public String toString() {
146         final StringBuilder sb = new StringBuilder();
147         for (int i = 0; i < mLength; i++) {
148             if (i != 0) {
149                 sb.append(",");
150             }
151             sb.append(mArray[i]);
152         }
153         return "[" + sb + "]";
154     }
155 }
156