/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed 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 com.badlogic.gdx.utils;
/** A sorted double linked list which uses ints for indexing
*
* @param <E> */
public class SortedIntList<E> implements Iterable<SortedIntList.Node<E>> {
private NodePool<E> nodePool = new NodePool<E>(); // avoid allocating nodes
private Iterator iterator;
int size = 0;
Node<E> first;
/** Creates an ascending list */
public SortedIntList () {
}
/** Inserts an element into the list at the given index
*
* @param index Index of the element
* @param value Element to insert
* @return Element replaced by newly inserted element, null if nothing was replaced */
public E insert (int index, E value) {
if (first != null) {
Node<E> c = first;
// iterate to the right until we can't move any further because the next number is bigger than index
while (c.n != null && c.n.index <= index) {
c = c.n;
}
// add one to the right
if (index > c.index) {
c.n = nodePool.obtain(c, c.n, value, index);
if (c.n.n != null) {
c.n.n.p = c.n;
}
size++;
}
// the new element is smaller than every other element
else if (index < c.index) {
Node<E> newFirst = nodePool.obtain(null, first, value, index);
first.p = newFirst;
first = newFirst;
size++;
}
// that element already exists so swap the value
else {
c.value = value;
}
} else {
first = nodePool.obtain(null, null, value, index);
size++;
}
return null;
}
/** Retrieves an element at a given index
*
* @param index Index of the element to retrieve
* @return Matching element, null otherwise */
public E get (int index) {
E match = null;
if (first != null) {
Node<E> c = first;
while (c.n != null && c.index < index) {
c = c.n;
}
if (c.index == index) {
match = c.value;
}
}
return match;
}
/** Clears list */
public void clear () {
for (; first != null; first = first.n) {
nodePool.free(first);
}
size = 0;
}
/** @return size of list equal to elements contained in it */
public int size () {
return size;
}
/** Returns an iterator to traverse the list.<br/>
* Only one iterator can be active per list at any given time.
*
* @return Iterator to traverse list */
public java.util.Iterator<Node<E>> iterator () {
if (iterator == null) {
iterator = new Iterator();
}
return iterator.reset();
}
class Iterator implements java.util.Iterator<Node<E>> {
private Node<E> position;
private Node<E> previousPosition;
@Override
public boolean hasNext () {
return position != null;
}
@Override
public Node<E> next () {
previousPosition = position;
position = position.n;
return previousPosition;
}
@Override
public void remove () {
// the contract specifies to remove the last returned element, if nothing was returned yet assumably do nothing
if (previousPosition != null) {
// if we are at the second element set it as the first element
if (previousPosition == first) {
first = position;
}
// else remove last returned element by changing the chain
else {
previousPosition.p.n = position;
if (position != null) {
position.p = previousPosition.p;
}
}
size--;
}
}
public Iterator reset () {
position = first;
previousPosition = null;
return this;
}
}
public static class Node<E> {
/** Node previous to this */
protected Node<E> p;
/** Node next to this */
protected Node<E> n;
/** Value held */
public E value;
/** Index value in list */
public int index;
}
static class NodePool<E> extends Pool<Node<E>> {
@Override
protected Node<E> newObject () {
return new Node<E>();
}
public Node<E> obtain (Node<E> p, Node<E> n, E value, int index) {
Node<E> newNode = super.obtain();
newNode.p = p;
newNode.n = n;
newNode.value = value;
newNode.index = index;
return newNode;
}
}
}