/*
* Copyright 2009-2016 Tilmann Zaeschke. All rights reserved.
*
* This file is part of ZooDB.
*
* ZooDB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ZooDB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ZooDB. If not, see <http://www.gnu.org/licenses/>.
*
* See the README and COPYING files for further information.
*/
package org.zoodb.internal.util;
import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
*
* @author Tilmann Zaeschke
*/
public class PrimLongArrayList implements Iterable<Long> {
private static final long[] EMPTY_LIST = {};
private static final int MIN_SIZE_INCREMENT = 10;
private int modCount = 0;
private int size;
private long[] list = EMPTY_LIST;
public PrimLongArrayList() {
//
}
/**
* @param val
* @return <tt>true</tt> if the list {@code val}
*/
public boolean contains(long val) {
for (int i = 0; i < size; i++) {
if (list[i] == val) {
return true;
}
}
return false;
}
public long get(int pos) {
checkPos(pos);
return list[pos];
}
private void checkPos(int pos) {
if (pos < 0 || pos >= size) {
throw new IndexOutOfBoundsException("pos=" + pos);
}
}
public void set(int pos, long value) {
checkPos(pos);
list[pos] = value;
}
public void add(long value) {
ensureCapacity(size + 1);
list[size] = value;
size++;
}
public long removePos(int pos) {
checkPos(pos);
long prevVal = list[pos];
removeNoCheck(pos);
return prevVal;
}
public boolean removeVal(long value) {
for (int i = 0; i < size; i++) {
if (list[i] == value) {
removeNoCheck(i);
return true;
}
}
return false;
}
public long removeFirst() {
return removePos(0);
}
public long removeLast() {
return removePos(size - 1);
}
private void removeNoCheck(int pos) {
modCount++;
size--;
int len = size - pos;
//TODO allow shrinking here?
if (len > 0) {
System.arraycopy(list, pos+1, list, pos, len);
}
}
public void addAll(Collection<Long> c) {
ensureCapacity(size + c.size());
for (Long l: c) {
list[size] = l;
size++;
}
}
public void addAll(PrimLongArrayList list2) {
ensureCapacity(size + list2.size);
System.arraycopy(list2.list, 0, list, size, list2.size);
size += list2.size;
}
private void ensureCapacity(int required) {
int toAdd = required - list.length;
if (toAdd <= 0) {
return;
}
int minIncrement = MIN_SIZE_INCREMENT < (size>>>1) ? (size >>>1) : MIN_SIZE_INCREMENT;
int newSize = size + ((toAdd < minIncrement) ? minIncrement : toAdd);
long[] newList = new long[newSize];
System.arraycopy(list, 0, newList, 0, size);
list = newList;
}
/**
* @return the size of the list
*/
public int size() {
return size;
}
/**
* @return {@code true} if the list is empty, othewise {@code false}
*/
public boolean isEmpty() {
return size == 0;
}
public void clear() {
modCount++;
list = EMPTY_LIST;
size = 0;
}
public long[] toArray() {
return Arrays.copyOf(list, size);
}
public LongIterator iterator() {
return new LongIterator();
}
public class LongIterator implements Iterator<Long> {
private int expectedModCount = modCount;
private int posNextToReturn = 0;
public boolean hasNext() {
return hasNextLong();
}
public Long next() {
return nextLong();
}
public boolean hasNextLong() {
return posNextToReturn < size;
}
public long nextLong() {
checkModCount();
if (!hasNextLong()) {
throw new NoSuchElementException();
}
return list[posNextToReturn++];
}
public void remove() {
checkModCount();
if (posNextToReturn <= 0) {
throw new IllegalStateException();
}
PrimLongArrayList.this.removeNoCheck(posNextToReturn - 1);
expectedModCount = modCount;
}
private void checkModCount() {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
}
}