19370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka/* 29370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka * Copyright (C) 2012 The Android Open Source Project 39370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka * 48aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); 58aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * you may not use this file except in compliance with the License. 68aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * You may obtain a copy of the License at 79370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka * 88aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 99370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka * 109370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software 118aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, 128aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * See the License for the specific language governing permissions and 148aa9963a895f9dd5bb1bc92ab2e4f461e058f87aTadashi G. Takaoka * limitations under the License. 159370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka */ 169370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 1736799b2aa2982ec17341cd2c5ed81e608bcee8c6Jean Chalardpackage com.android.inputmethod.latin.common; 189370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 1954bf24f64b9bbd4c5e4b6d4c3c6144c047d6ddc6Mohammadinamul Sheikimport com.android.inputmethod.annotations.UsedForTesting; 2054bf24f64b9bbd4c5e4b6d4c3c6144c047d6ddc6Mohammadinamul Sheik 219370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaokaimport java.util.Arrays; 229370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 23519df535996427c87242f8dbdd5993c6ab5a87d0Tadashi G. Takaokaimport javax.annotation.Nonnull; 24519df535996427c87242f8dbdd5993c6ab5a87d0Tadashi G. Takaoka 259370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka// TODO: This class is not thread-safe. 26a28a05e971cc242b338331a3b78276fa95188d19Tadashi G. Takaokapublic final class ResizableIntArray { 27519df535996427c87242f8dbdd5993c6ab5a87d0Tadashi G. Takaoka @Nonnull 289370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka private int[] mArray; 299370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka private int mLength; 309370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 31c49c85f835ecd14d09abb6d88c85a3303c566741Tadashi G. Takaoka public ResizableIntArray(final int capacity) { 329370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka reset(capacity); 339370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka } 349370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 35c49c85f835ecd14d09abb6d88c85a3303c566741Tadashi G. Takaoka public int get(final int index) { 367abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka if (index < mLength) { 377abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka return mArray[index]; 38c49c85f835ecd14d09abb6d88c85a3303c566741Tadashi G. Takaoka } 397abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka throw new ArrayIndexOutOfBoundsException("length=" + mLength + "; index=" + index); 40c49c85f835ecd14d09abb6d88c85a3303c566741Tadashi G. Takaoka } 41c49c85f835ecd14d09abb6d88c85a3303c566741Tadashi G. Takaoka 42ad78058a93492d4f114c6a6eb56177be9231a9ebTadashi G. Takaoka public void addAt(final int index, final int val) { 437abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka if (index < mLength) { 447abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka mArray[index] = val; 457abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka } else { 469370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka mLength = index; 479370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka add(val); 489370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka } 499370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka } 509370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 51c49c85f835ecd14d09abb6d88c85a3303c566741Tadashi G. Takaoka public void add(final int val) { 527abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka final int currentLength = mLength; 537abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka ensureCapacity(currentLength + 1); 547abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka mArray[currentLength] = val; 557abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka mLength = currentLength + 1; 567abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka } 577abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka 587abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka /** 597abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka * Calculate the new capacity of {@code mArray}. 607abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka * @param minimumCapacity the minimum capacity that the {@code mArray} should have. 617abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka * @return the new capacity that the {@code mArray} should have. Returns zero when there is no 627abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka * need to expand {@code mArray}. 637abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka */ 647abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka private int calculateCapacity(final int minimumCapacity) { 657abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka final int currentCapcity = mArray.length; 667abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka if (currentCapcity < minimumCapacity) { 677abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka final int nextCapacity = currentCapcity * 2; 687abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka // The following is the same as return Math.max(minimumCapacity, nextCapacity); 697abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka return minimumCapacity > nextCapacity ? minimumCapacity : nextCapacity; 707abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka } 717abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka return 0; 729370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka } 739370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 74c49c85f835ecd14d09abb6d88c85a3303c566741Tadashi G. Takaoka private void ensureCapacity(final int minimumCapacity) { 757abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka final int newCapacity = calculateCapacity(minimumCapacity); 767abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka if (newCapacity > 0) { 779370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka // TODO: Implement primitive array pool. 787abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka mArray = Arrays.copyOf(mArray, newCapacity); 799370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka } 809370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka } 819370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 829370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka public int getLength() { 839370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka return mLength; 849370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka } 859370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 86c49c85f835ecd14d09abb6d88c85a3303c566741Tadashi G. Takaoka public void setLength(final int newLength) { 87c49c85f835ecd14d09abb6d88c85a3303c566741Tadashi G. Takaoka ensureCapacity(newLength); 88c49c85f835ecd14d09abb6d88c85a3303c566741Tadashi G. Takaoka mLength = newLength; 89c49c85f835ecd14d09abb6d88c85a3303c566741Tadashi G. Takaoka } 909370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 91c49c85f835ecd14d09abb6d88c85a3303c566741Tadashi G. Takaoka public void reset(final int capacity) { 929370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka // TODO: Implement primitive array pool. 939370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka mArray = new int[capacity]; 949370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka mLength = 0; 959370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka } 969370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 97519df535996427c87242f8dbdd5993c6ab5a87d0Tadashi G. Takaoka @Nonnull 989370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka public int[] getPrimitiveArray() { 999370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka return mArray; 1009370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka } 1019370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 102519df535996427c87242f8dbdd5993c6ab5a87d0Tadashi G. Takaoka public void set(@Nonnull final ResizableIntArray ip) { 1039370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka // TODO: Implement primitive array pool. 1049370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka mArray = ip.mArray; 1059370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka mLength = ip.mLength; 1069370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka } 1079370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 108519df535996427c87242f8dbdd5993c6ab5a87d0Tadashi G. Takaoka public void copy(@Nonnull final ResizableIntArray ip) { 1097abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka final int newCapacity = calculateCapacity(ip.mLength); 1107abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka if (newCapacity > 0) { 1117abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka // TODO: Implement primitive array pool. 1127abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka mArray = new int[newCapacity]; 1137abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka } 1149370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka System.arraycopy(ip.mArray, 0, mArray, 0, ip.mLength); 1159370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka mLength = ip.mLength; 1169370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka } 1179370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka 118519df535996427c87242f8dbdd5993c6ab5a87d0Tadashi G. Takaoka public void append(@Nonnull final ResizableIntArray src, final int startPos, final int length) { 1197abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka if (length == 0) { 1207abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka return; 1217abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka } 1229370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka final int currentLength = mLength; 1239370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka final int newLength = currentLength + length; 1249370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka ensureCapacity(newLength); 1259370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka System.arraycopy(src.mArray, startPos, mArray, currentLength, length); 1269370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka mLength = newLength; 1279370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka } 1287abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka 1297abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka public void fill(final int value, final int startPos, final int length) { 1307abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka if (startPos < 0 || length < 0) { 1317abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka throw new IllegalArgumentException("startPos=" + startPos + "; length=" + length); 1327abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka } 1337abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka final int endPos = startPos + length; 1347abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka ensureCapacity(endPos); 1357abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka Arrays.fill(mArray, startPos, endPos, value); 1367abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka if (mLength < endPos) { 1377abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka mLength = endPos; 1387abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka } 1397abdcf1ed3113d3c121f6ff1b87a7464f079e141Tadashi G. Takaoka } 14064ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka 141e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi /** 142e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi * Shift to the left by elementCount, discarding elementCount pointers at the start. 143e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi * @param elementCount how many elements to shift. 144e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi */ 14554bf24f64b9bbd4c5e4b6d4c3c6144c047d6ddc6Mohammadinamul Sheik @UsedForTesting 146e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi public void shift(final int elementCount) { 147e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi System.arraycopy(mArray, elementCount, mArray, 0, mLength - elementCount); 148e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi mLength -= elementCount; 149e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi } 150e8754aba1c8f217e7ca828de25e0506ac58daa99Keisuke Kuroyanagi 15164ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka @Override 15264ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka public String toString() { 15364ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka final StringBuilder sb = new StringBuilder(); 15464ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka for (int i = 0; i < mLength; i++) { 15564ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka if (i != 0) { 15664ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka sb.append(","); 15764ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka } 15864ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka sb.append(mArray[i]); 15964ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka } 16064ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka return "[" + sb + "]"; 16164ee09610024eb1436c51f9c9ef9fc3f77239d73Tadashi G. Takaoka } 1629370ab9adad3b4bc3af8bde52b6422b8d2b873e7Tadashi G. Takaoka} 163