Last active
December 6, 2024 22:38
-
-
Save Miha-x64/ec39faec7098fad2aaaa96bec87a52b8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@file:Suppress("UNCHECKED_CAST", "NAME_SHADOWING") | |
/** | |
* this.filterIndexed(inPredicate).mapIndexed(transform).filterIndexed(outPredicate).take(limit) | |
*/ | |
inline fun <T, R> List<T>.mapFilterLimiting( | |
fromIndex: Int = 0, | |
toIndex: Int = size, | |
inPredicate: (index: Int, T) -> Boolean = { _: Any?, _: Any? -> true }, | |
transform: (index: Int, T) -> R, | |
outPredicate: (index: Int, R) -> Boolean = { _: Any?, _: Any? -> true }, | |
limit: Int = Int.MAX_VALUE, | |
): List<R> { | |
if (fromIndex < 0 || toIndex < fromIndex || toIndex > size) thrBadRange(fromIndex, toIndex, size) | |
if (limit < 0) thrNegLim(limit) | |
if (limit == 0 || fromIndex == toIndex) return emptyList() | |
var i = fromIndex | |
var ti = 0 | |
var first: R? = null | |
i = search( | |
i, toIndex, | |
stop = { i -> get(i).let { inPredicate(i, it) && outPredicate(ti, transform(ti++, it).also { first = it }) } }, | |
block = {}, | |
missing = { return emptyList() }, | |
) | |
if (limit == 1) return listOf(first as R) | |
var second: R? = null | |
i = search( | |
i, toIndex, | |
stop = { i -> get(i).let { inPredicate(i, it) && outPredicate(ti, transform(ti++, it).also { second = it }) } }, | |
block = {}, | |
missing = { return listOf(first as R) }, | |
) | |
val destination = ArrayList<R>(minOf(toIndex - fromIndex, limit, 10)).also { it.add(first as R); it.add(second as R) } | |
var count = 2 | |
i = search( | |
i, toIndex, | |
stop = { count == limit }, | |
block = { i -> | |
val it = get(i) | |
if (inPredicate(i, it)) | |
transform(ti, it).also { r -> | |
if (outPredicate(ti++, r)) { | |
destination.add(r) | |
count++ | |
} | |
} | |
}, | |
missing = {}, | |
) | |
return destination | |
} | |
/** | |
* destination += this.filterIndexed(inPredicate).mapIndexed(transform).filterIndexed(outPredicate).take(limit) | |
*/ | |
inline fun <C : MutableCollection<in R>, T, R> List<T>.mapFilterLimitingTo( | |
destination: C, | |
fromIndex: Int = 0, | |
toIndex: Int = size, | |
inPredicate: (index: Int, T) -> Boolean = { _: Any?, _: Any? -> true }, | |
transform: (index: Int, T) -> R, | |
outPredicate: (index: Int, R) -> Boolean = { _: Any?, _: Any? -> true }, | |
limit: Int = Int.MAX_VALUE, | |
): C { | |
if (fromIndex < 0 || toIndex < fromIndex || toIndex > size) thrBadRange(fromIndex, toIndex, size) | |
if (limit < 0) thrNegLim(limit) | |
if (limit == 0 || fromIndex == toIndex) return destination | |
var ti = 0 | |
var count = 0 | |
search( | |
fromIndex, toIndex, | |
stop = { count == limit }, | |
block = { i -> | |
val it = get(i) | |
if (inPredicate(i, it)) | |
transform(ti, it).also { r -> | |
if (outPredicate(ti++, r)) { | |
destination.add(r) | |
count++ | |
} | |
} | |
}, | |
missing = {}, | |
) | |
return destination | |
} | |
/** | |
* this.filterIndexed(inPredicate).mapIndexed(transform).filterIndexed(outPredicate).take(limit) | |
*/ | |
inline fun <T, R> Iterator<T>.mapFilterLimiting( | |
inPredicate: (index: Int, T) -> Boolean = { _: Any?, _: Any? -> true }, | |
transform: (index: Int, T) -> R, | |
outPredicate: (index: Int, R) -> Boolean = { _: Any?, _: Any? -> true }, | |
limit: Int = Int.MAX_VALUE, | |
): List<R> { | |
if (limit < 0) thrNegLim(limit) | |
if (limit == 0) return emptyList() | |
var i = 0 | |
var ti = 0 | |
var first: R? = null | |
while (true) { | |
if (!hasNext()) return emptyList() | |
val t = next() | |
if (inPredicate(i++, t) && outPredicate(ti, transform(ti++, t).also { first = it })) break | |
} | |
if (limit == 1) return listOf(first as R) | |
var second: R? = null | |
while (true) { | |
if (!hasNext()) return listOf(first as R) | |
val t = next() | |
if (inPredicate(i++, t) && outPredicate(ti, transform(ti++, t).also { second = it })) break | |
} | |
val destination = ArrayList<R>(minOf(limit, 10)).also { it.add(first as R); it.add(second as R) } | |
var count = 2 | |
while (count < limit && hasNext()) { | |
val t = next() | |
if (inPredicate(i++, t)) | |
transform(ti, t).also { r -> | |
if (outPredicate(ti++, r)) { | |
destination.add(r) | |
count++ | |
} | |
} | |
} | |
return destination | |
} | |
/** | |
* destination += this.filterIndexed(inPredicate).mapIndexed(transform).filterIndexed(outPredicate).take(limit) | |
*/ | |
inline fun <C : MutableCollection<in R>, T, R> Iterator<T>.mapFilterLimitingTo( | |
destination: C, | |
inPredicate: (index: Int, T) -> Boolean = { _: Any?, _: Any? -> true }, | |
transform: (index: Int, T) -> R, | |
outPredicate: (index: Int, R) -> Boolean = { _: Any?, _: Any? -> true }, | |
limit: Int = Int.MAX_VALUE, | |
): C { | |
if (limit < 0) thrNegLim(limit) | |
if (limit == 0) return destination | |
var i = 0 | |
var ti = 0 | |
var count = 0 | |
while (count < limit && hasNext()) { | |
val t = next() | |
if (inPredicate(i++, t)) | |
transform(ti, t).also { r -> | |
if (outPredicate(ti++, r)) { | |
destination.add(r) | |
count++ | |
} | |
} | |
} | |
return destination | |
} | |
@PublishedApi internal fun thrBadRange(from: Int, to: Int, size: Int): Unit = // less bytecode than Nothing | |
throw IllegalArgumentException("Inapplicable range [$from, $to) for List[$size]") | |
@PublishedApi internal fun thrNegLim(limit: Int): Unit = | |
throw IllegalArgumentException("Negative limit: $limit") | |
@PublishedApi internal // dafuq?? wannabe private, it's inline after all | |
inline fun search( | |
from: Int, until: Int, | |
stop: (Int) -> Boolean, block: (Int) -> Unit, missing: () -> Unit, | |
): Int { | |
var i = from | |
while (i < until) | |
if (stop(i)) return i + 1 else block(i++) | |
missing() | |
return i | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment