refactor
This commit is contained in:
128
src/main/kotlin/blitz/collections/Batched.kt
Normal file
128
src/main/kotlin/blitz/collections/Batched.kt
Normal file
@@ -0,0 +1,128 @@
|
||||
package blitz.collections
|
||||
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
interface BatchIterator<T>: Iterator<T> {
|
||||
fun next(limit: Int): List<T>
|
||||
fun next(dest: Array<T>): Int
|
||||
fun next(dest: MutableList<T>, limit: Int)
|
||||
}
|
||||
|
||||
interface ByteBatchIterator: BatchIterator<Byte> {
|
||||
fun nextBytes(limit: Int): ByteArray
|
||||
|
||||
fun nextBytes(dest: ByteArray): Int
|
||||
}
|
||||
|
||||
interface BatchSequence<T>: Sequence<T> {
|
||||
override fun iterator(): BatchIterator<T>
|
||||
}
|
||||
|
||||
interface ByteBatchSequence: BatchSequence<Byte> {
|
||||
override fun iterator(): ByteBatchIterator
|
||||
}
|
||||
|
||||
/**
|
||||
* Batches all get operations on the sequence.
|
||||
*/
|
||||
fun <T> BatchSequence<T>.batched(count: Int): BatchSequence<T> =
|
||||
object : BatchSequence<T> {
|
||||
inner class Iter: BatchIterator<T> {
|
||||
val parent = this@batched.iterator()
|
||||
|
||||
var batch = mutableListOf<T>()
|
||||
|
||||
override fun next(limit: Int): List<T> {
|
||||
if (!hasNext())
|
||||
throw Exception("no next")
|
||||
|
||||
val c = min(limit, batch.size)
|
||||
val ret = batch.take(c)
|
||||
batch.removeFirst(c)
|
||||
return ret
|
||||
}
|
||||
|
||||
override fun next(dest: MutableList<T>, limit: Int) {
|
||||
if (!hasNext())
|
||||
throw Exception("no next")
|
||||
|
||||
val c = min(limit, batch.size)
|
||||
dest.addAll(batch.subList(0, max(0, c-1)))
|
||||
batch.removeFirst(c)
|
||||
return
|
||||
}
|
||||
|
||||
override fun next(dest: Array<T>): Int {
|
||||
if (!hasNext())
|
||||
throw Exception("no next")
|
||||
|
||||
val c = min(dest.size, batch.size)
|
||||
batch.subList(0, max(0, c-1)).forEachIndexed { i, t ->
|
||||
dest[i] = t
|
||||
}
|
||||
batch.removeFirst(c)
|
||||
return c
|
||||
}
|
||||
|
||||
override fun next(): T {
|
||||
if (!hasNext())
|
||||
throw Exception("no next")
|
||||
val v = batch.first()
|
||||
batch.removeFirst()
|
||||
return v
|
||||
}
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
while (batch.isEmpty()) {
|
||||
if (!parent.hasNext())
|
||||
return false
|
||||
parent.next(batch, count)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
override fun iterator(): BatchIterator<T> =
|
||||
Iter()
|
||||
}
|
||||
|
||||
fun <T> Sequence<T>.asBatch(): BatchSequence<T> =
|
||||
object : BatchSequence<T> {
|
||||
inner class Iter: BatchIterator<T> {
|
||||
var iter = this@asBatch.iterator()
|
||||
|
||||
override fun next(limit: Int): List<T> =
|
||||
mutableListOf<T>()
|
||||
.also { next(it, limit) }
|
||||
|
||||
override fun next(dest: MutableList<T>, limit: Int) {
|
||||
for (i in 0..<limit) {
|
||||
if (!iter.hasNext())
|
||||
break
|
||||
dest.add(iter.next())
|
||||
}
|
||||
}
|
||||
|
||||
override fun next(dest: Array<T>): Int {
|
||||
var i = 0
|
||||
while (i < dest.size) {
|
||||
if (!iter.hasNext())
|
||||
break
|
||||
dest[i ++] = iter.next()
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
override fun next(): T {
|
||||
return iter.next()
|
||||
}
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
return iter.hasNext()
|
||||
}
|
||||
}
|
||||
|
||||
override fun iterator(): BatchIterator<T> =
|
||||
Iter()
|
||||
}
|
10
src/main/kotlin/blitz/collections/BatchedUtils.kt
Normal file
10
src/main/kotlin/blitz/collections/BatchedUtils.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
package blitz.collections
|
||||
|
||||
fun ByteBatchSequence.stringify(batch: Int = 64): Sequence<String> {
|
||||
val iter = iterator()
|
||||
return generateSequence {
|
||||
if (iter.hasNext())
|
||||
iter.nextBytes(batch).decodeToString()
|
||||
else null
|
||||
}
|
||||
}
|
51
src/main/kotlin/blitz/collections/Contents.kt
Normal file
51
src/main/kotlin/blitz/collections/Contents.kt
Normal file
@@ -0,0 +1,51 @@
|
||||
package blitz.collections
|
||||
|
||||
class Contents<T> internal constructor(
|
||||
private val iterable: Iterable<T>
|
||||
): Iterable<T> {
|
||||
override fun iterator(): Iterator<T> =
|
||||
iterable.iterator()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is Contents<*>)
|
||||
return false
|
||||
|
||||
val it1 = this.iterable.iterator()
|
||||
val it2 = other.iterable.iterator()
|
||||
|
||||
while (true) {
|
||||
val hasNext1 = it1.hasNext()
|
||||
val hasNext2 = it2.hasNext()
|
||||
|
||||
if ((hasNext1 && !hasNext2) || (hasNext2 && !hasNext1))
|
||||
return false
|
||||
|
||||
if (!hasNext1)
|
||||
return true
|
||||
|
||||
if (it1.next() != it2.next())
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
override fun hashCode(): Int =
|
||||
iterable.hashCode()
|
||||
|
||||
override fun toString(): String =
|
||||
joinToString(
|
||||
separator = ", ",
|
||||
prefix = "[",
|
||||
postfix = "]"
|
||||
) {
|
||||
it.toString()
|
||||
}
|
||||
}
|
||||
|
||||
val <T> Iterable<T>.contents get() =
|
||||
Contents(this)
|
||||
|
||||
val <T> Sequence<T>.contents get() =
|
||||
Contents(this.asIterable())
|
||||
|
||||
val <T> Array<T>.contents get() =
|
||||
Contents(this.asIterable())
|
13
src/main/kotlin/blitz/collections/ListOps.kt
Normal file
13
src/main/kotlin/blitz/collections/ListOps.kt
Normal file
@@ -0,0 +1,13 @@
|
||||
package blitz.collections
|
||||
|
||||
fun <T> MutableList<T>.removeFirst(count: Int) {
|
||||
repeat(count) {
|
||||
removeFirst()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> MutableList<T>.removeLast(count: Int) {
|
||||
repeat(count) {
|
||||
removeLast()
|
||||
}
|
||||
}
|
42
src/main/kotlin/blitz/collections/SequenceBase.kt
Normal file
42
src/main/kotlin/blitz/collections/SequenceBase.kt
Normal file
@@ -0,0 +1,42 @@
|
||||
package blitz.collections
|
||||
|
||||
interface IndexableSequence<T>: Sequence<T> {
|
||||
operator fun get(index: Int): T
|
||||
}
|
||||
|
||||
fun <T> IndexableSequence<T>.modifier(mod: (Sequence<T>) -> Sequence<T>) =
|
||||
object : IndexableSequence<T> {
|
||||
val other = mod(this@modifier)
|
||||
|
||||
override fun iterator(): Iterator<T> =
|
||||
other.iterator()
|
||||
|
||||
override fun get(index: Int): T =
|
||||
this@modifier[index]
|
||||
}
|
||||
|
||||
fun <T> Sequence<T>.asIndexable(): IndexableSequence<T> =
|
||||
object : IndexableSequence<T> {
|
||||
val iter = this@asIndexable.iterator()
|
||||
val values = mutableListOf<T>()
|
||||
|
||||
override fun get(index: Int): T {
|
||||
if (index >= values.size) {
|
||||
repeat(index + 1 - values.size) {
|
||||
values.add(iter.next())
|
||||
}
|
||||
}
|
||||
return values[index]
|
||||
}
|
||||
|
||||
override fun iterator(): Iterator<T> =
|
||||
object : Iterator<T> {
|
||||
var i = 0
|
||||
|
||||
override fun hasNext(): Boolean =
|
||||
i < values.size || iter.hasNext()
|
||||
|
||||
override fun next(): T =
|
||||
get(i ++)
|
||||
}
|
||||
}
|
77
src/main/kotlin/blitz/collections/SequenceCreators.kt
Normal file
77
src/main/kotlin/blitz/collections/SequenceCreators.kt
Normal file
@@ -0,0 +1,77 @@
|
||||
package blitz.collections
|
||||
|
||||
import blitz.Obj
|
||||
import blitz.Provider
|
||||
import kotlin.math.max
|
||||
|
||||
fun <T> lazySequence(vararg init: Pair<Int, T>, default: Obj<T>?, f: (Int, (Int) -> T) -> T): IndexableSequence<T> =
|
||||
object : IndexableSequence<T> {
|
||||
val map = mutableMapOf(*init)
|
||||
|
||||
var current: Int? = null
|
||||
|
||||
fun comp(iIn: Int): T {
|
||||
val i = max(0, iIn)
|
||||
if (current == i)
|
||||
return (default ?: throw Exception("recursion detected")).v
|
||||
return map[i] ?: let {
|
||||
current = i
|
||||
val res = f(i, ::comp)
|
||||
map[i] = res
|
||||
current = null
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
override fun get(index: Int) = comp(index)
|
||||
|
||||
override fun iterator(): Iterator<T> =
|
||||
object : Iterator<T> {
|
||||
override fun hasNext() = true
|
||||
|
||||
private var i = 0
|
||||
|
||||
override fun next(): T =
|
||||
comp(i ++)
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> easySequence(vararg init: Pair<Int, T?>, f: (Int, (Int) -> T?) -> T?): Sequence<T?> =
|
||||
lazySequence(*init, default = Obj.of(null)) { i, ff ->
|
||||
f(i) { index ->
|
||||
var indexC = index
|
||||
var v: T? = null
|
||||
while (indexC > 0 && v == null)
|
||||
v = ff(indexC --)
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
fun <I, T> Sequence<I>.easyMappingSequence(
|
||||
vararg init: Pair<Int, T?>,
|
||||
f: (Int, (Int) -> T?, (Int) -> I) -> T?
|
||||
): Sequence<T?> {
|
||||
val indexable = this.asIndexable()
|
||||
return easySequence(*init) { i, ff ->
|
||||
f(i, ff, indexable::get)
|
||||
}.limitBy(indexable)
|
||||
.removeNull()
|
||||
}
|
||||
|
||||
fun <T> selfInitializingSequence(block: Provider<Sequence<T>>): Sequence<T> =
|
||||
object : Sequence<T> {
|
||||
val seq by lazy(block)
|
||||
|
||||
inner class Iter : Iterator<T> {
|
||||
val iter = seq.iterator()
|
||||
|
||||
override fun hasNext(): Boolean =
|
||||
iter.hasNext()
|
||||
|
||||
override fun next(): T =
|
||||
iter.next()
|
||||
}
|
||||
|
||||
override fun iterator(): Iterator<T> =
|
||||
Iter()
|
||||
}
|
25
src/main/kotlin/blitz/collections/SequenceOps.kt
Normal file
25
src/main/kotlin/blitz/collections/SequenceOps.kt
Normal file
@@ -0,0 +1,25 @@
|
||||
package blitz.collections
|
||||
|
||||
fun <T> Sequence<T>.removeNull(): Sequence<T> =
|
||||
mapNotNull { it }
|
||||
|
||||
fun <T> IndexableSequence<T>.removeNull(): IndexableSequence<T> =
|
||||
modifier { it.removeNull() }
|
||||
|
||||
fun <A, B> Sequence<A>.limitBy(other: Sequence<B>): Sequence<A> =
|
||||
object : Sequence<A> {
|
||||
override fun iterator(): Iterator<A> =
|
||||
object : Iterator<A> {
|
||||
val s = this@limitBy.iterator()
|
||||
val o = other.iterator()
|
||||
|
||||
override fun hasNext(): Boolean =
|
||||
o.hasNext() && s.hasNext()
|
||||
|
||||
override fun next(): A =
|
||||
s.next().also { o.next() }
|
||||
}
|
||||
}
|
||||
|
||||
fun <A, B> IndexableSequence<A>.limitBy(other: Sequence<B>): IndexableSequence<A> =
|
||||
modifier { it.limitBy(other) }
|
Reference in New Issue
Block a user