/* * JVSTM: a Java library for Software Transactional Memory * Copyright (C) 2005 INESC-ID Software Engineering Group * http://www.esw.inesc-id.pt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Author's contact: * INESC-ID Software Engineering Group * Rua Alves Redol 9 * 1000 - 029 Lisboa * Portugal */ package jvstm.util; import java.util.Iterator; import java.util.NoSuchElementException; public final class Cons<E> implements Iterable<E> { protected static final Cons EMPTY = new Cons(null, null); public final static <T> Cons<T> empty() { return (Cons<T>)EMPTY; } protected final E first; protected final Cons<E> rest; private Cons(E first, Cons<E> rest) { this.first = first; this.rest = rest; } public final Cons<E> cons(E elem) { return new Cons<E>(elem, this); } public final E first() { if (isEmpty()) { throw new EmptyListException(); } else { return first; } } public final Cons<E> rest() { if (isEmpty()) { throw new EmptyListException(); } else { return rest; } } public final Cons<E> removeFirst(Object elem) { Cons<E> found = member(elem); if (found == null) { return this; } else { return removeExistingCons(found); } } public final Cons<E> removeAll(Object elem) { Cons<E> lastFound = lastMember(elem); if (lastFound == null) { return this; } else if (lastFound == this) { return rest; } else { // skip over conses containing the elem Cons<E> next = this; if (elem == null) { while ((next != lastFound) && (next.first == null)) { next = next.rest; } } else { while ((next != lastFound) && (elem.equals(next.first))) { next = next.rest; } } if (next == lastFound) { return next.rest; } // We have to allocate new Cons cells until we reach the lastFound cons Cons<E> newCons = ((Cons<E>)EMPTY).cons(next.first); next = next.rest; if (elem == null) { while (next != lastFound) { if (next.first != null) { newCons = newCons.cons(next.first); } next = next.rest; } } else { while (next != lastFound) { if (! elem.equals(next.first)) { newCons = newCons.cons(next.first); } next = next.rest; } } // share the rest newCons = newCons.reverseInto(next.rest); return newCons; } } public final Cons<E> removeCons(Cons<?> cons) { Cons<?> iter = this; while ((iter != cons) && (iter != EMPTY)) { iter = iter.rest; } if (iter == EMPTY) { return this; } else { return removeExistingCons(cons); } } private final Cons<E> removeExistingCons(Cons<?> cons) { if (cons == this) { return rest; } else { // We have to allocate new Cons cells until we reach the cons to remove Cons<E> newCons = ((Cons<E>)EMPTY).cons(first); Cons<E> next = rest; while (next != cons) { newCons = newCons.cons(next.first); next = next.rest; } // share the rest newCons = newCons.reverseInto(next.rest); return newCons; } } public final int size() { int size = 0; Cons<?> iter = this; while (iter != EMPTY) { size++; iter = iter.rest; } return size; } public final boolean isEmpty() { return (this == EMPTY); } public final boolean contains(Object elem) { return member(elem) != null; } public final Cons<E> member(Object elem) { Cons<E> iter = this; if (elem == null) { while (iter != EMPTY) { if (iter.first == null) { return iter; } iter = iter.rest; } } else { while (iter != EMPTY) { if (elem.equals(iter.first)) { return iter; } iter = iter.rest; } } return null; } public final Cons<E> lastMember(Object elem) { Cons<E> found = null; Cons<E> iter = this; if (elem == null) { while (iter != EMPTY) { if (iter.first == null) { found = iter; } iter = iter.rest; } } else { while (iter != EMPTY) { if (elem.equals(iter.first)) { found = iter; } iter = iter.rest; } } return found; } public final Cons<E> reverse() { return reverseInto((Cons<E>)EMPTY); } public final Cons<E> reverseInto(Cons<E> tail) { Cons<E> result = tail; Cons<E> iter = this; while (iter != EMPTY) { result = result.cons(iter.first); iter = iter.rest; } return result; } public final Iterator<E> iterator() { return new ConsIterator<E>(this); } final static class ConsIterator<T> implements Iterator<T> { private Cons<T> current; ConsIterator(Cons<T> start) { this.current = start; } public final boolean hasNext() { return (current != EMPTY); } public final T next() { if (current == EMPTY) { throw new NoSuchElementException(); } else { T result = current.first; current = current.rest; return result; } } public final void remove() { throw new UnsupportedOperationException(); } } }