Home | History | Annotate | Download | only in common
      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 
     31     public ResizableIntArray(final int capacity) {
     32         reset(capacity);
     33     }
     34 
     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 
     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 
     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      */
     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 
     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 
     82     public int getLength() {
     83         return mLength;
     84     }
     85 
     86     public void setLength(final int newLength) {
     87         ensureCapacity(newLength);
     88         mLength = newLength;
     89     }
     90 
     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
     98     public int[] getPrimitiveArray() {
     99         return mArray;
    100     }
    101 
    102     public void set(@Nonnull final ResizableIntArray ip) {
    103         // TODO: Implement primitive array pool.
    104         mArray = ip.mArray;
    105         mLength = ip.mLength;
    106     }
    107 
    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 
    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 
    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
    146     public void shift(final int elementCount) {
    147         System.arraycopy(mArray, elementCount, mArray, 0, mLength - elementCount);
    148         mLength -= elementCount;
    149     }
    150 
    151     @Override
    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