/* sbt -- Simple Build Tool * Copyright 2010 Mark Harrah */ package sbt /** A mutable set interface that uses object identity to test for set membership.*/ trait IDSet[T] { def apply(t: T): Boolean def contains(t: T): Boolean def += (t: T): Unit def ++=(t: Iterable[T]): Unit def -= (t: T): Boolean def all: collection.Iterable[T] def isEmpty: Boolean def foreach(f: T => Unit): Unit def process[S](t: T)(ifSeen: S)(ifNew: => S): S } object IDSet { implicit def toTraversable[T]: IDSet[T] => Traversable[T] = _.all def apply[T](values: T*): IDSet[T] = apply(values) def apply[T](values: Iterable[T]): IDSet[T] = { val s = create[T] s ++= values s } def create[T]: IDSet[T] = new IDSet[T] { private[this] val backing = new java.util.IdentityHashMap[T, AnyRef] private[this] val Dummy: AnyRef = "" def apply(t: T) = contains(t) def contains(t: T) = backing.containsKey(t) def foreach(f: T => Unit) = all foreach f def += (t: T) = backing.put(t, Dummy) def ++=(t: Iterable[T]) = t foreach += def -= (t:T) = if(backing.remove(t) eq null) false else true def all = collection.JavaConversions.asIterable(backing.keySet) def isEmpty = backing.isEmpty def process[S](t: T)(ifSeen: S)(ifNew: => S) = if(contains(t)) ifSeen else { this += t ; ifNew } override def toString = backing.toString } }