/*
* Copyright 2023 dorkbox, llc
*
* 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.
*/
/*******************************************************************************
* Copyright 2011 LibGDX.
* Mario Zechner @gmail.com>
* Nathan Sweet @gmail.com>
*
* 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 dorkbox.collections
/** Interface used to select items within an iterator against a predicate.
* @author Xoppa
*/
interface Predicate {
/** @return true if the item matches the criteria and should be included in the iterators items
*/
fun evaluate(arg0: T): Boolean
class PredicateIterator(iterator: MutableIterator, predicate: Predicate?) : MutableIterator {
var iterator: MutableIterator? = null
var predicate: Predicate? = null
var end = false
var peeked = false
var next: T? = null
constructor(iterable: Iterable, predicate: Predicate?) : this(iterable.iterator() as MutableIterator, predicate)
init {
set(iterator, predicate)
}
operator fun set(iterable: Iterable, predicate: Predicate?) {
set(iterable.iterator() as MutableIterator, predicate)
}
operator fun set(iterator: MutableIterator, predicate: Predicate?) {
this.iterator = iterator
this.predicate = predicate
peeked = false
end = peeked
next = null
}
override fun hasNext(): Boolean {
if (end) return false
if (next != null) return true
peeked = true
while (iterator!!.hasNext()) {
val n = iterator!!.next()
if (predicate!!.evaluate(n)) {
next = n
return true
}
}
end = true
return false
}
override fun next(): T? {
if (next == null && !hasNext()) return null
val result = next
next = null
peeked = false
return result
}
override fun remove() {
if (peeked) throw RuntimeException("Cannot remove between a call to hasNext() and next().")
iterator!!.remove()
}
}
class PredicateIterable(iterable: Iterable?, predicate: Predicate?) : Iterable {
var iterable: Iterable? = null
var predicate: Predicate? = null
var iterator: PredicateIterator? = null
init {
set(iterable, predicate)
}
operator fun set(iterable: Iterable?, predicate: Predicate?) {
this.iterable = iterable
this.predicate = predicate
}
/** Returns an iterator. Note that the same iterator instance is returned each time this method is called. Use the
* [Predicate.PredicateIterator] constructor for nested or multithreaded iteration. */
override fun iterator(): MutableIterator {
if (iterator == null) {
iterator = PredicateIterator(iterable!!.iterator() as MutableIterator, predicate)
}
else {
iterator!!.set(iterable!!.iterator() as MutableIterator, predicate)
}
@Suppress("UNCHECKED_CAST")
return iterator as MutableIterator
}
}
}