package tc.oc.commons.bukkit.util;
import gnu.trove.TLongCollection;
import gnu.trove.iterator.TLongIterator;
import java.util.NoSuchElementException;
/**
* Minimal implementation of a FIFO queue of longs, stored efficiently in a primitive array.
* Does not implement {@link gnu.trove.queue.TLongQueue} because it would be more trouble
* than its worth to us.
*/
public class LongDeque {
public static final int DEFAULT_CAPACITY = 16;
private final long noEntryValue;
private long[] buf;
private int head, tail;
public LongDeque() {
this(DEFAULT_CAPACITY, 0);
}
public LongDeque(int capacity, long noEntryValue) {
this.noEntryValue = noEntryValue;
buf = new long[capacity];
}
private int advance(int index) {
index++;
return index < buf.length ? index : 0;
}
private void ensureCapacity(int delta) {
int capacity = size() + delta;
if (capacity >= buf.length) {
// Find the smallest power of 2 that is big enough
capacity |= (capacity >>> 1);
capacity |= (capacity >>> 2);
capacity |= (capacity >>> 4);
capacity |= (capacity >>> 8);
capacity |= (capacity >>> 16);
capacity++;
long[] bigger = new long[capacity];
if(tail > head) {
System.arraycopy(buf, head, bigger, 0, tail - head);
tail -= head;
} else {
System.arraycopy(buf, head, bigger, 0, buf.length - head);
System.arraycopy(buf, 0, bigger, buf.length - head, tail);
tail += buf.length - head;
}
head = 0;
buf = bigger;
}
}
/**
* Return head
*/
public long peek() {
if(isEmpty()) {
return getNoEntryValue();
} else {
return buf[head];
}
}
/**
* Return head, throw if empty
*/
public long element() {
if(isEmpty()) throw new NoSuchElementException("queue is empty");
return peek();
}
/**
* Remove from head
*/
public long poll() {
if(isEmpty()) {
return getNoEntryValue();
} else {
long value = buf[head];
head = advance(head);
return value;
}
}
/**
* Remove from head, throw if empty
*/
public long remove() {
if(isEmpty()) throw new NoSuchElementException("queue is empty");
return poll();
}
private void addUnchecked(long value) {
buf[tail] = value;
tail = advance(tail);
}
/**
* Add to head
*/
public void offer(long value) {
add(value);
}
/**
* Add to head
*/
public void add(long value) {
ensureCapacity(1);
addUnchecked(value);
}
public void addAll(TLongCollection values) {
ensureCapacity(values.size());
for(TLongIterator iter = values.iterator(); iter.hasNext();) {
addUnchecked(iter.next());
}
}
public void clear() {
buf = new long[DEFAULT_CAPACITY];
head = tail = 0;
}
public long getNoEntryValue() {
return noEntryValue;
}
public int size() {
int n = tail - head;
if(n < 0) n += buf.length;
return n;
}
public boolean isEmpty() {
return head == tail;
}
public boolean contains(long entry) {
for(int i = head; i != tail; i = advance(i)) {
if(buf[i] == entry) return true;
}
return false;
}
}