122 lines
4.3 KiB
Kotlin
Vendored
122 lines
4.3 KiB
Kotlin
Vendored
@file:kotlin.jvm.JvmMultifileClass
|
|
@file:kotlin.jvm.JvmName("SequencesKt")
|
|
|
|
package kotlin.sequences
|
|
|
|
public inline fun <T> Sequence(crossinline iterator: () -> Iterator<T>): Sequence<T> = object : Sequence<T> {
|
|
override fun iterator(): Iterator<T> = iterator()
|
|
}
|
|
|
|
public fun <T> Iterator<T>.asSequence(): Sequence<T> = Sequence { this }//.constrainOnce()
|
|
|
|
public fun <T> sequenceOf(vararg elements: T): Sequence<T> = if (elements.isEmpty()) emptySequence() else elements.asSequence()
|
|
|
|
public fun <T> emptySequence(): Sequence<T> = EmptySequence
|
|
|
|
private object EmptySequence : Sequence<Nothing>, DropTakeSequence<Nothing> {
|
|
override fun iterator(): Iterator<Nothing> = EmptyIterator
|
|
override fun drop(n: Int) = EmptySequence
|
|
override fun take(n: Int) = EmptySequence
|
|
}
|
|
|
|
public inline fun <T> Sequence<T>?.orEmpty(): Sequence<T> = this ?: emptySequence()
|
|
|
|
private class GeneratorSequence<T : Any>(private val getInitialValue: () -> T?, private val getNextValue: (T) -> T?) : Sequence<T> {
|
|
override fun iterator(): Iterator<T> = object : Iterator<T> {
|
|
var nextItem: T? = null
|
|
var nextState: Int = -2 // -2 for initial unknown, -1 for next unknown, 0 for done, 1 for continue
|
|
|
|
private fun calcNext() {
|
|
nextItem = if (nextState == -2) getInitialValue() else getNextValue(nextItem!!)
|
|
nextState = if (nextItem == null) 0 else 1
|
|
}
|
|
|
|
override fun next(): T {
|
|
if (nextState < 0)
|
|
calcNext()
|
|
|
|
if (nextState == 0)
|
|
throw NoSuchElementException()
|
|
val result = nextItem as T
|
|
// Do not clean nextItem (to avoid keeping reference on yielded instance) -- need to keep state for getNextValue
|
|
nextState = -1
|
|
return result
|
|
}
|
|
|
|
override fun hasNext(): Boolean {
|
|
if (nextState < 0)
|
|
calcNext()
|
|
return nextState == 1
|
|
}
|
|
}
|
|
}
|
|
|
|
public fun <T : Any> generateSequence(nextFunction: () -> T?): Sequence<T> {
|
|
return GeneratorSequence(nextFunction, { nextFunction() })//.constrainOnce()
|
|
}
|
|
|
|
public fun <T : Any> generateSequence(seed: T?, nextFunction: (T) -> T?): Sequence<T> =
|
|
if (seed == null)
|
|
EmptySequence
|
|
else
|
|
GeneratorSequence({ seed }, nextFunction)
|
|
|
|
public fun <T : Any> generateSequence(seedFunction: () -> T?, nextFunction: (T) -> T?): Sequence<T> =
|
|
GeneratorSequence(seedFunction, nextFunction)
|
|
|
|
public operator fun <T> Sequence<T>.contains(element: T): Boolean {
|
|
return indexOf(element) >= 0
|
|
}
|
|
|
|
public fun <T> Sequence<T>.indexOf(element: T): Int {
|
|
var index = 0
|
|
for (item in this) {
|
|
checkIndexOverflow(index)
|
|
if (element == item)
|
|
return index
|
|
index++
|
|
}
|
|
return -1
|
|
}
|
|
|
|
public fun <T> Sequence<T>.toList(): List<T> {
|
|
return this.toMutableList().optimizeReadOnlyList()
|
|
}
|
|
|
|
public fun <T> Sequence<T>.toMutableList(): MutableList<T> {
|
|
return toCollection(ArrayList<T>())
|
|
}
|
|
|
|
public fun <T, C : MutableCollection<in T>> Sequence<T>.toCollection(destination: C): C {
|
|
for (item in this) {
|
|
destination.add(item)
|
|
}
|
|
return destination
|
|
}
|
|
|
|
public fun <T> Sequence<T>.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String {
|
|
return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString()
|
|
}
|
|
|
|
public fun <T, A : Appendable> Sequence<T>.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): A {
|
|
buffer.append(prefix)
|
|
var count = 0
|
|
for (element in this) {
|
|
if (++count > 1) buffer.append(separator)
|
|
if (limit < 0 || count <= limit) {
|
|
buffer.appendElement(element, transform)
|
|
} else break
|
|
}
|
|
if (limit >= 0 && count > limit) buffer.append(truncated)
|
|
buffer.append(postfix)
|
|
return buffer
|
|
}
|
|
|
|
private fun <T> Appendable.appendElement(element: T, transform: ((T) -> CharSequence)?) {
|
|
when {
|
|
transform != null -> append(transform(element))
|
|
element is CharSequence? -> append(element)
|
|
element is Char -> append(element)
|
|
else -> append(element.toString())
|
|
}
|
|
} |