| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.harmony.pack200; |
| |
| import java.util.Arrays; |
| |
| /** |
| * IntList is based on <code>java.util.ArrayList</code>, but is written |
| * specifically for ints in order to reduce boxing and unboxing to Integers, |
| * reduce the memory required and improve performance of pack200. |
| */ |
| public class IntList { |
| |
| private int[] array; |
| private int firstIndex; |
| private int lastIndex; |
| private int modCount; |
| |
| /** |
| * Constructs a new instance of IntList with capacity for ten elements. |
| */ |
| public IntList() { |
| this(10); |
| } |
| |
| /** |
| * Constructs a new instance of IntList with the specified capacity. |
| * |
| * @param capacity |
| * the initial capacity of this IntList |
| */ |
| public IntList(int capacity) { |
| if (capacity < 0) { |
| throw new IllegalArgumentException(); |
| } |
| firstIndex = lastIndex = 0; |
| array = new int[capacity]; |
| } |
| |
| /** |
| * Adds the specified object at the end of this IntList. |
| * |
| * @param object |
| * the object to add |
| * @return true |
| */ |
| public boolean add(int object) { |
| if (lastIndex == array.length) { |
| growAtEnd(1); |
| } |
| array[lastIndex++] = object; |
| modCount++; |
| return true; |
| } |
| |
| public void add(int location, int object) { |
| int size = lastIndex - firstIndex; |
| if (0 < location && location < size) { |
| if (firstIndex == 0 && lastIndex == array.length) { |
| growForInsert(location, 1); |
| } else if ((location < size / 2 && firstIndex > 0) |
| || lastIndex == array.length) { |
| System.arraycopy(array, firstIndex, array, --firstIndex, |
| location); |
| } else { |
| int index = location + firstIndex; |
| System.arraycopy(array, index, array, index + 1, size |
| - location); |
| lastIndex++; |
| } |
| array[location + firstIndex] = object; |
| } else if (location == 0) { |
| if (firstIndex == 0) { |
| growAtFront(1); |
| } |
| array[--firstIndex] = object; |
| } else if (location == size) { |
| if (lastIndex == array.length) { |
| growAtEnd(1); |
| } |
| array[lastIndex++] = object; |
| } else { |
| throw new IndexOutOfBoundsException(); |
| } |
| |
| modCount++; |
| } |
| |
| public void clear() { |
| if (firstIndex != lastIndex) { |
| Arrays.fill(array, firstIndex, lastIndex, -1); |
| firstIndex = lastIndex = 0; |
| modCount++; |
| } |
| } |
| |
| public int get(int location) { |
| if (0 <= location && location < (lastIndex - firstIndex)) { |
| return array[firstIndex + location]; |
| } |
| throw new IndexOutOfBoundsException("" + location); |
| } |
| |
| private void growAtEnd(int required) { |
| int size = lastIndex - firstIndex; |
| if (firstIndex >= required - (array.length - lastIndex)) { |
| int newLast = lastIndex - firstIndex; |
| if (size > 0) { |
| System.arraycopy(array, firstIndex, array, 0, size); |
| } |
| firstIndex = 0; |
| lastIndex = newLast; |
| } else { |
| int increment = size / 2; |
| if (required > increment) { |
| increment = required; |
| } |
| if (increment < 12) { |
| increment = 12; |
| } |
| int[] newArray = new int[size + increment]; |
| if (size > 0) { |
| System.arraycopy(array, firstIndex, newArray, 0, size); |
| firstIndex = 0; |
| lastIndex = size; |
| } |
| array = newArray; |
| } |
| } |
| |
| private void growAtFront(int required) { |
| int size = lastIndex - firstIndex; |
| if (array.length - lastIndex + firstIndex >= required) { |
| int newFirst = array.length - size; |
| if (size > 0) { |
| System.arraycopy(array, firstIndex, array, newFirst, size); |
| } |
| firstIndex = newFirst; |
| lastIndex = array.length; |
| } else { |
| int increment = size / 2; |
| if (required > increment) { |
| increment = required; |
| } |
| if (increment < 12) { |
| increment = 12; |
| } |
| int[] newArray = new int[size + increment]; |
| if (size > 0) { |
| System.arraycopy(array, firstIndex, newArray, newArray.length |
| - size, size); |
| } |
| firstIndex = newArray.length - size; |
| lastIndex = newArray.length; |
| array = newArray; |
| } |
| } |
| |
| private void growForInsert(int location, int required) { |
| int size = lastIndex - firstIndex; |
| int increment = size / 2; |
| if (required > increment) { |
| increment = required; |
| } |
| if (increment < 12) { |
| increment = 12; |
| } |
| int[] newArray = new int[size + increment]; |
| int newFirst = increment - required; |
| // Copy elements after location to the new array skipping inserted |
| // elements |
| System.arraycopy(array, location + firstIndex, newArray, newFirst |
| + location + required, size - location); |
| // Copy elements before location to the new array from firstIndex |
| System.arraycopy(array, firstIndex, newArray, newFirst, location); |
| firstIndex = newFirst; |
| lastIndex = size + increment; |
| |
| array = newArray; |
| } |
| |
| public void increment(int location) { |
| if (0 <= location && location < (lastIndex - firstIndex)) { |
| array[firstIndex + location]++; |
| } else { |
| throw new IndexOutOfBoundsException("" + location); |
| } |
| } |
| |
| public boolean isEmpty() { |
| return lastIndex == firstIndex; |
| } |
| |
| public int remove(int location) { |
| int result; |
| int size = lastIndex - firstIndex; |
| if (0 <= location && location < size) { |
| if (location == size - 1) { |
| result = array[--lastIndex]; |
| array[lastIndex] = 0; |
| } else if (location == 0) { |
| result = array[firstIndex]; |
| array[firstIndex++] = 0; |
| } else { |
| int elementIndex = firstIndex + location; |
| result = array[elementIndex]; |
| if (location < size / 2) { |
| System.arraycopy(array, firstIndex, array, firstIndex + 1, |
| location); |
| array[firstIndex++] = 0; |
| } else { |
| System.arraycopy(array, elementIndex + 1, array, |
| elementIndex, size - location - 1); |
| array[--lastIndex] = 0; |
| } |
| } |
| if (firstIndex == lastIndex) { |
| firstIndex = lastIndex = 0; |
| } |
| } else { |
| throw new IndexOutOfBoundsException(); |
| } |
| |
| modCount++; |
| return result; |
| } |
| |
| public int size() { |
| return lastIndex - firstIndex; |
| } |
| |
| public int[] toArray() { |
| int size = lastIndex - firstIndex; |
| int[] result = new int[size]; |
| System.arraycopy(array, firstIndex, result, 0, size); |
| return result; |
| } |
| |
| public void addAll(IntList list) { |
| growAtEnd(list.size()); |
| for (int i = 0; i < list.size(); i++) { |
| add(list.get(i)); |
| } |
| } |
| |
| } |