/*******************************************************************************
* Copyright (c) 2012 Google, Inc and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.parser.util;
import java.util.Arrays;
/**
* Automatically growing integer array.
*
* @since 5.5
*/
public class IntArray {
private static final int INITIAL_CAPACITY = 10;
private static final int[] EMPTY_ARRAY = {};
private int[] buffer = EMPTY_ARRAY;
private int size;
public IntArray() {
}
public IntArray(int initialCapacity) {
this.buffer = new int[initialCapacity];
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void add(int value) {
grow(size + 1);
buffer[size++] = value;
}
public void add(int index, int value) {
checkBounds(index);
grow(size + 1);
System.arraycopy(buffer, index, buffer, index + 1, size - index);
buffer[index] = value;
size++;
}
public void addAll(IntArray other) {
grow(size + other.size());
System.arraycopy(other.buffer, 0, buffer, size, other.size);
size += other.size;
return;
}
public void addAll(int[] array) {
grow(size + array.length);
System.arraycopy(array, 0, buffer, size, array.length);
size += array.length;
return;
}
public int remove(int index) {
checkBounds(index);
int old = buffer[index];
int n = size - index - 1;
if (n > 0) {
System.arraycopy(buffer, index + 1, buffer, index, n);
}
return old;
}
public void remove(int from, int to) {
checkBounds(from);
checkBounds(to);
System.arraycopy(buffer, to, buffer, from, size - to);
}
public void clear() {
size = 0;
}
public int get(int index) {
checkRange(index);
return buffer[index];
}
public int set(int index, int value) {
checkBounds(index);
int old = buffer[index];
buffer[index] = value;
return old;
}
public int[] toArray() {
return size == 0 ? EMPTY_ARRAY : Arrays.copyOf(buffer, size);
}
public void trimToSize() {
if (size == 0) {
buffer = EMPTY_ARRAY;
} else if (size < buffer.length) {
buffer = Arrays.copyOf(buffer, size);
}
}
public void ensureCapacity(int minCapacity) {
if (minCapacity > 0) {
grow(minCapacity);
}
}
private void grow(int minCapacity) {
if (minCapacity < 0) // Overflow
throw new OutOfMemoryError();
int capacity = buffer.length;
if (minCapacity > capacity) {
int newCapacity = capacity == 0 ? INITIAL_CAPACITY : capacity + (capacity >> 1);
// newCapacity may be negative due to overflow.
if (newCapacity < minCapacity)
newCapacity = minCapacity;
// newCapacity is guaranteed to be non negative.
try {
buffer = Arrays.copyOf(buffer, newCapacity);
} catch (OutOfMemoryError e) {
// Try again it case we were too aggressive in reserving capacity.
buffer = Arrays.copyOf(buffer, minCapacity);
}
}
}
private void checkBounds(int index) {
if (index < 0) {
throw new IndexOutOfBoundsException("Negative index: " + index); //$NON-NLS-1$
}
checkRange(index);
}
private void checkRange(int index) {
if (index >= size) {
throw new IndexOutOfBoundsException("Index: " + index + ", size: " + size); //$NON-NLS-1$//$NON-NLS-2$
}
}
}