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