From c0cac21b8a3170b2d6ec1e077562a78e557f0b5f Mon Sep 17 00:00:00 2001 From: James Strachan Date: Fri, 23 Mar 2012 11:03:38 +0000 Subject: [PATCH] added a helper method to filter a subset of an iterator by sub type --- libraries/stdlib/src/Iterators.kt | 20 ++++++ .../stdlib/src/support/AbstractIterator.kt | 72 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 libraries/stdlib/src/support/AbstractIterator.kt diff --git a/libraries/stdlib/src/Iterators.kt b/libraries/stdlib/src/Iterators.kt index 8350e149e34..18e2d233f09 100644 --- a/libraries/stdlib/src/Iterators.kt +++ b/libraries/stdlib/src/Iterators.kt @@ -1,5 +1,7 @@ package kotlin.util +import kotlin.support.AbstractIterator + import java.util.* import java.util.Iterator @@ -24,3 +26,21 @@ inline fun java.util.Iterator.toLinkedHashSet() = to(LinkedHashSet()) /** Add iterated elements to java.util.TreeSet */ inline fun java.util.Iterator.toTreeSet() = to(TreeSet()) + +/** Filters the iterator for all elements of a certain kind */ +inline fun java.util.Iterator.filterIs(): Iterator { + val iter = this + return object : AbstractIterator() { + + override fun computeNext(): R? { + while (iter.hasNext()) { + val next = iter.next() + if (next is R) { + return next as R + } + } + done() + return null + } + } +} \ No newline at end of file diff --git a/libraries/stdlib/src/support/AbstractIterator.kt b/libraries/stdlib/src/support/AbstractIterator.kt new file mode 100644 index 00000000000..0990595c5e5 --- /dev/null +++ b/libraries/stdlib/src/support/AbstractIterator.kt @@ -0,0 +1,72 @@ +package kotlin.support + +import java.util.* + +// TODO should we use enums? +private val Ready = 0 +private val NotReady = 1 +private val Done = 2 +private val Failed = 3 + +/** + * A base class to simplify implementing iterators so that implementations only have to implement [[#computeNext()]] + * to implement the iterator, calling [[done()]] when the iteration is complete. + */ +abstract class AbstractIterator: Iterator { + var state = NotReady + var next: T? = null + + override fun hasNext(): Boolean { + require(state != Failed) + return when (state) { + Done -> false + Ready -> true + else -> tryToComputeNext() + } + } + + override fun next(): T { + if (!hasNext()) { + throw NoSuchElementException(); + } else { + state = NotReady + return next.sure() + } + } + + override fun remove() { + throw UnsupportedOperationException() + } + + /** + * Returns the next element in the iteration without advancing the iteration + */ + fun peek(): T { + if (!hasNext()) { + throw NoSuchElementException(); + } + return next.sure(); + } + + private fun tryToComputeNext(): Boolean { + state = Failed + next = computeNext(); + return if (state != Done) { + state = Ready + true + } else false + } + + /** + * Computes the next element in the iterator, calling endOfData() when + * there are no more elements + */ + abstract protected fun computeNext(): T? + + /** + * Sets the state to done so that the iteration terminates + */ + protected fun done() { + state = Done + } +} \ No newline at end of file