/* * 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 } } }