Make sure index and count do not overflow for long sequences
Throw an exception immediately before an overflow becomes observable. Place check to prevent negative index from indexOf, indexOfFirst. Do not insert overflow checks for arrays, lists, maps and char sequences. #KT-16097
This commit is contained in:
@@ -9701,7 +9701,7 @@ public inline fun CharArray.count(): Int {
|
|||||||
*/
|
*/
|
||||||
public inline fun <T> Array<out T>.count(predicate: (T) -> Boolean): Int {
|
public inline fun <T> Array<out T>.count(predicate: (T) -> Boolean): Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) ++count
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9710,7 +9710,7 @@ public inline fun <T> Array<out T>.count(predicate: (T) -> Boolean): Int {
|
|||||||
*/
|
*/
|
||||||
public inline fun ByteArray.count(predicate: (Byte) -> Boolean): Int {
|
public inline fun ByteArray.count(predicate: (Byte) -> Boolean): Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) ++count
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9719,7 +9719,7 @@ public inline fun ByteArray.count(predicate: (Byte) -> Boolean): Int {
|
|||||||
*/
|
*/
|
||||||
public inline fun ShortArray.count(predicate: (Short) -> Boolean): Int {
|
public inline fun ShortArray.count(predicate: (Short) -> Boolean): Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) ++count
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9728,7 +9728,7 @@ public inline fun ShortArray.count(predicate: (Short) -> Boolean): Int {
|
|||||||
*/
|
*/
|
||||||
public inline fun IntArray.count(predicate: (Int) -> Boolean): Int {
|
public inline fun IntArray.count(predicate: (Int) -> Boolean): Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) ++count
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9737,7 +9737,7 @@ public inline fun IntArray.count(predicate: (Int) -> Boolean): Int {
|
|||||||
*/
|
*/
|
||||||
public inline fun LongArray.count(predicate: (Long) -> Boolean): Int {
|
public inline fun LongArray.count(predicate: (Long) -> Boolean): Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) ++count
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9746,7 +9746,7 @@ public inline fun LongArray.count(predicate: (Long) -> Boolean): Int {
|
|||||||
*/
|
*/
|
||||||
public inline fun FloatArray.count(predicate: (Float) -> Boolean): Int {
|
public inline fun FloatArray.count(predicate: (Float) -> Boolean): Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) ++count
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9755,7 +9755,7 @@ public inline fun FloatArray.count(predicate: (Float) -> Boolean): Int {
|
|||||||
*/
|
*/
|
||||||
public inline fun DoubleArray.count(predicate: (Double) -> Boolean): Int {
|
public inline fun DoubleArray.count(predicate: (Double) -> Boolean): Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) ++count
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9764,7 +9764,7 @@ public inline fun DoubleArray.count(predicate: (Double) -> Boolean): Int {
|
|||||||
*/
|
*/
|
||||||
public inline fun BooleanArray.count(predicate: (Boolean) -> Boolean): Int {
|
public inline fun BooleanArray.count(predicate: (Boolean) -> Boolean): Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) ++count
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9773,7 +9773,7 @@ public inline fun BooleanArray.count(predicate: (Boolean) -> Boolean): Int {
|
|||||||
*/
|
*/
|
||||||
public inline fun CharArray.count(predicate: (Char) -> Boolean): Int {
|
public inline fun CharArray.count(predicate: (Char) -> Boolean): Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) ++count
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13504,7 +13504,7 @@ public fun Array<out Byte>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
++count
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -13518,7 +13518,7 @@ public fun Array<out Short>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
++count
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -13532,7 +13532,7 @@ public fun Array<out Int>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
++count
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -13546,7 +13546,7 @@ public fun Array<out Long>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
++count
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -13560,7 +13560,7 @@ public fun Array<out Float>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
++count
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -13574,7 +13574,7 @@ public fun Array<out Double>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
++count
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -13587,7 +13587,7 @@ public fun ByteArray.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
++count
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -13600,7 +13600,7 @@ public fun ShortArray.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
++count
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -13613,7 +13613,7 @@ public fun IntArray.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
++count
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -13626,7 +13626,7 @@ public fun LongArray.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
++count
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -13639,7 +13639,7 @@ public fun FloatArray.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
++count
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -13652,7 +13652,7 @@ public fun DoubleArray.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
++count
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -251,6 +251,7 @@ public fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.indexOf(element: T):
|
|||||||
if (this is List) return this.indexOf(element)
|
if (this is List) return this.indexOf(element)
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) {
|
for (item in this) {
|
||||||
|
checkIndexOverflow(index)
|
||||||
if (element == item)
|
if (element == item)
|
||||||
return index
|
return index
|
||||||
index++
|
index++
|
||||||
@@ -272,6 +273,7 @@ public fun <@kotlin.internal.OnlyInputTypes T> List<T>.indexOf(element: T): Int
|
|||||||
public inline fun <T> Iterable<T>.indexOfFirst(predicate: (T) -> Boolean): Int {
|
public inline fun <T> Iterable<T>.indexOfFirst(predicate: (T) -> Boolean): Int {
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) {
|
for (item in this) {
|
||||||
|
checkIndexOverflow(index)
|
||||||
if (predicate(item))
|
if (predicate(item))
|
||||||
return index
|
return index
|
||||||
index++
|
index++
|
||||||
@@ -299,6 +301,7 @@ public inline fun <T> Iterable<T>.indexOfLast(predicate: (T) -> Boolean): Int {
|
|||||||
var lastIndex = -1
|
var lastIndex = -1
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) {
|
for (item in this) {
|
||||||
|
checkIndexOverflow(index)
|
||||||
if (predicate(item))
|
if (predicate(item))
|
||||||
lastIndex = index
|
lastIndex = index
|
||||||
index++
|
index++
|
||||||
@@ -387,6 +390,7 @@ public fun <@kotlin.internal.OnlyInputTypes T> Iterable<T>.lastIndexOf(element:
|
|||||||
var lastIndex = -1
|
var lastIndex = -1
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) {
|
for (item in this) {
|
||||||
|
checkIndexOverflow(index)
|
||||||
if (element == item)
|
if (element == item)
|
||||||
lastIndex = index
|
lastIndex = index
|
||||||
index++
|
index++
|
||||||
@@ -1258,7 +1262,7 @@ public inline fun <T, R : Any, C : MutableCollection<in R>> Iterable<T>.mapIndex
|
|||||||
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapIndexedTo(destination: C, transform: (index: Int, T) -> R): C {
|
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapIndexedTo(destination: C, transform: (index: Int, T) -> R): C {
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this)
|
for (item in this)
|
||||||
destination.add(transform(index++, item))
|
destination.add(transform(checkIndexOverflow(index++), item))
|
||||||
return destination
|
return destination
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1407,7 +1411,7 @@ public inline fun <T> Iterable<T>.any(predicate: (T) -> Boolean): Boolean {
|
|||||||
public fun <T> Iterable<T>.count(): Int {
|
public fun <T> Iterable<T>.count(): Int {
|
||||||
if (this is Collection) return size
|
if (this is Collection) return size
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) count++
|
for (element in this) checkCountOverflow(++count)
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1425,7 +1429,7 @@ public inline fun <T> Collection<T>.count(): Int {
|
|||||||
public inline fun <T> Iterable<T>.count(predicate: (T) -> Boolean): Int {
|
public inline fun <T> Iterable<T>.count(predicate: (T) -> Boolean): Int {
|
||||||
if (this is Collection && isEmpty()) return 0
|
if (this is Collection && isEmpty()) return 0
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) checkCountOverflow(++count)
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1447,7 +1451,7 @@ public inline fun <T, R> Iterable<T>.fold(initial: R, operation: (acc: R, T) ->
|
|||||||
public inline fun <T, R> Iterable<T>.foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R {
|
public inline fun <T, R> Iterable<T>.foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R {
|
||||||
var index = 0
|
var index = 0
|
||||||
var accumulator = initial
|
var accumulator = initial
|
||||||
for (element in this) accumulator = operation(index++, accumulator, element)
|
for (element in this) accumulator = operation(checkIndexOverflow(index++), accumulator, element)
|
||||||
return accumulator
|
return accumulator
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1498,7 +1502,7 @@ public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
|
|||||||
*/
|
*/
|
||||||
public inline fun <T> Iterable<T>.forEachIndexed(action: (index: Int, T) -> Unit): Unit {
|
public inline fun <T> Iterable<T>.forEachIndexed(action: (index: Int, T) -> Unit): Unit {
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) action(index++, item)
|
for (item in this) action(checkIndexOverflow(index++), item)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1725,7 +1729,7 @@ public inline fun <S, T : S> Iterable<T>.reduceIndexed(operation: (index: Int, a
|
|||||||
var index = 1
|
var index = 1
|
||||||
var accumulator: S = iterator.next()
|
var accumulator: S = iterator.next()
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
accumulator = operation(index++, accumulator, iterator.next())
|
accumulator = operation(checkIndexOverflow(index++), accumulator, iterator.next())
|
||||||
}
|
}
|
||||||
return accumulator
|
return accumulator
|
||||||
}
|
}
|
||||||
@@ -2238,7 +2242,7 @@ public fun Iterable<Byte>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
checkCountOverflow(++count)
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -2252,7 +2256,7 @@ public fun Iterable<Short>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
checkCountOverflow(++count)
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -2266,7 +2270,7 @@ public fun Iterable<Int>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
checkCountOverflow(++count)
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -2280,7 +2284,7 @@ public fun Iterable<Long>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
checkCountOverflow(++count)
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -2294,7 +2298,7 @@ public fun Iterable<Float>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
checkCountOverflow(++count)
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -2308,7 +2312,7 @@ public fun Iterable<Double>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
checkCountOverflow(++count)
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public inline fun <K, V> Map<out K, V>.count(): Int {
|
|||||||
public inline fun <K, V> Map<out K, V>.count(predicate: (Map.Entry<K, V>) -> Boolean): Int {
|
public inline fun <K, V> Map<out K, V>.count(predicate: (Map.Entry<K, V>) -> Boolean): Int {
|
||||||
if (isEmpty()) return 0
|
if (isEmpty()) return 0
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) ++count
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ public inline fun <T> Sequence<T>.firstOrNull(predicate: (T) -> Boolean): T? {
|
|||||||
public fun <@kotlin.internal.OnlyInputTypes T> Sequence<T>.indexOf(element: T): Int {
|
public fun <@kotlin.internal.OnlyInputTypes T> Sequence<T>.indexOf(element: T): Int {
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) {
|
for (item in this) {
|
||||||
|
checkIndexOverflow(index)
|
||||||
if (element == item)
|
if (element == item)
|
||||||
return index
|
return index
|
||||||
index++
|
index++
|
||||||
@@ -161,6 +162,7 @@ public fun <@kotlin.internal.OnlyInputTypes T> Sequence<T>.indexOf(element: T):
|
|||||||
public inline fun <T> Sequence<T>.indexOfFirst(predicate: (T) -> Boolean): Int {
|
public inline fun <T> Sequence<T>.indexOfFirst(predicate: (T) -> Boolean): Int {
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) {
|
for (item in this) {
|
||||||
|
checkIndexOverflow(index)
|
||||||
if (predicate(item))
|
if (predicate(item))
|
||||||
return index
|
return index
|
||||||
index++
|
index++
|
||||||
@@ -177,6 +179,7 @@ public inline fun <T> Sequence<T>.indexOfLast(predicate: (T) -> Boolean): Int {
|
|||||||
var lastIndex = -1
|
var lastIndex = -1
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) {
|
for (item in this) {
|
||||||
|
checkIndexOverflow(index)
|
||||||
if (predicate(item))
|
if (predicate(item))
|
||||||
lastIndex = index
|
lastIndex = index
|
||||||
index++
|
index++
|
||||||
@@ -229,6 +232,7 @@ public fun <@kotlin.internal.OnlyInputTypes T> Sequence<T>.lastIndexOf(element:
|
|||||||
var lastIndex = -1
|
var lastIndex = -1
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) {
|
for (item in this) {
|
||||||
|
checkIndexOverflow(index)
|
||||||
if (element == item)
|
if (element == item)
|
||||||
lastIndex = index
|
lastIndex = index
|
||||||
index++
|
index++
|
||||||
@@ -852,7 +856,7 @@ public inline fun <T, R : Any, C : MutableCollection<in R>> Sequence<T>.mapIndex
|
|||||||
public inline fun <T, R, C : MutableCollection<in R>> Sequence<T>.mapIndexedTo(destination: C, transform: (index: Int, T) -> R): C {
|
public inline fun <T, R, C : MutableCollection<in R>> Sequence<T>.mapIndexedTo(destination: C, transform: (index: Int, T) -> R): C {
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this)
|
for (item in this)
|
||||||
destination.add(transform(index++, item))
|
destination.add(transform(checkIndexOverflow(index++), item))
|
||||||
return destination
|
return destination
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -976,7 +980,7 @@ public inline fun <T> Sequence<T>.any(predicate: (T) -> Boolean): Boolean {
|
|||||||
*/
|
*/
|
||||||
public fun <T> Sequence<T>.count(): Int {
|
public fun <T> Sequence<T>.count(): Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) count++
|
for (element in this) checkCountOverflow(++count)
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -987,7 +991,7 @@ public fun <T> Sequence<T>.count(): Int {
|
|||||||
*/
|
*/
|
||||||
public inline fun <T> Sequence<T>.count(predicate: (T) -> Boolean): Int {
|
public inline fun <T> Sequence<T>.count(predicate: (T) -> Boolean): Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) checkCountOverflow(++count)
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1013,7 +1017,7 @@ public inline fun <T, R> Sequence<T>.fold(initial: R, operation: (acc: R, T) ->
|
|||||||
public inline fun <T, R> Sequence<T>.foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R {
|
public inline fun <T, R> Sequence<T>.foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R {
|
||||||
var index = 0
|
var index = 0
|
||||||
var accumulator = initial
|
var accumulator = initial
|
||||||
for (element in this) accumulator = operation(index++, accumulator, element)
|
for (element in this) accumulator = operation(checkIndexOverflow(index++), accumulator, element)
|
||||||
return accumulator
|
return accumulator
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1035,7 +1039,7 @@ public inline fun <T> Sequence<T>.forEach(action: (T) -> Unit): Unit {
|
|||||||
*/
|
*/
|
||||||
public inline fun <T> Sequence<T>.forEachIndexed(action: (index: Int, T) -> Unit): Unit {
|
public inline fun <T> Sequence<T>.forEachIndexed(action: (index: Int, T) -> Unit): Unit {
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) action(index++, item)
|
for (item in this) action(checkIndexOverflow(index++), item)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1293,7 +1297,7 @@ public inline fun <S, T : S> Sequence<T>.reduceIndexed(operation: (index: Int, a
|
|||||||
var index = 1
|
var index = 1
|
||||||
var accumulator: S = iterator.next()
|
var accumulator: S = iterator.next()
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
accumulator = operation(index++, accumulator, iterator.next())
|
accumulator = operation(checkIndexOverflow(index++), accumulator, iterator.next())
|
||||||
}
|
}
|
||||||
return accumulator
|
return accumulator
|
||||||
}
|
}
|
||||||
@@ -1696,7 +1700,7 @@ public fun Sequence<Byte>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
checkCountOverflow(++count)
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -1712,7 +1716,7 @@ public fun Sequence<Short>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
checkCountOverflow(++count)
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -1728,7 +1732,7 @@ public fun Sequence<Int>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
checkCountOverflow(++count)
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -1744,7 +1748,7 @@ public fun Sequence<Long>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
checkCountOverflow(++count)
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -1760,7 +1764,7 @@ public fun Sequence<Float>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
checkCountOverflow(++count)
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
@@ -1776,7 +1780,7 @@ public fun Sequence<Double>.average(): Double {
|
|||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
checkCountOverflow(++count)
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -883,7 +883,7 @@ public inline fun CharSequence.count(): Int {
|
|||||||
*/
|
*/
|
||||||
public inline fun CharSequence.count(predicate: (Char) -> Boolean): Int {
|
public inline fun CharSequence.count(predicate: (Char) -> Boolean): Int {
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) ++count
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package kotlin.collections
|
package kotlin.collections
|
||||||
|
|
||||||
import kotlin.comparisons.naturalOrder
|
import kotlin.comparisons.naturalOrder
|
||||||
|
import kotlin.internal.InlineOnly
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
/** Returns the array if it's not `null`, or an empty array otherwise. */
|
/** Returns the array if it's not `null`, or an empty array otherwise. */
|
||||||
@@ -140,3 +141,22 @@ internal actual inline fun <T> Array<out T>.copyToArrayOfAny(isVarargs: Boolean)
|
|||||||
this
|
this
|
||||||
else
|
else
|
||||||
this.copyOf()
|
this.copyOf()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
internal actual fun checkIndexOverflow(index: Int): Int {
|
||||||
|
if (index < 0) {
|
||||||
|
throwIndexOverflow()
|
||||||
|
}
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
internal actual fun checkCountOverflow(count: Int): Int {
|
||||||
|
if (count < 0) {
|
||||||
|
throwCountOverflow()
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
package kotlin.collections
|
package kotlin.collections
|
||||||
|
|
||||||
import kotlin.*
|
import kotlin.*
|
||||||
|
import kotlin.internal.InlineOnly
|
||||||
|
import kotlin.internal.apiVersionIsAtLeast
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an immutable list containing only the specified object [element].
|
* Returns an immutable list containing only the specified object [element].
|
||||||
@@ -42,3 +44,31 @@ internal actual fun <T> Array<out T>.copyToArrayOfAny(isVarargs: Boolean): Array
|
|||||||
@Suppress("UNCHECKED_CAST") (this as Array<Any?>)
|
@Suppress("UNCHECKED_CAST") (this as Array<Any?>)
|
||||||
else
|
else
|
||||||
java.util.Arrays.copyOf(this, this.size, Array<Any?>::class.java)
|
java.util.Arrays.copyOf(this, this.size, Array<Any?>::class.java)
|
||||||
|
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@InlineOnly
|
||||||
|
internal actual inline fun checkIndexOverflow(index: Int): Int {
|
||||||
|
if (index < 0) {
|
||||||
|
if (apiVersionIsAtLeast(1, 3, 0))
|
||||||
|
throwIndexOverflow()
|
||||||
|
else
|
||||||
|
throw ArithmeticException("Index overflow has happened.")
|
||||||
|
}
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
@InlineOnly
|
||||||
|
internal actual inline fun checkCountOverflow(count: Int): Int {
|
||||||
|
if (count < 0) {
|
||||||
|
if (apiVersionIsAtLeast(1, 3, 0))
|
||||||
|
throwCountOverflow()
|
||||||
|
else
|
||||||
|
throw ArithmeticException("Count overflow has happened.")
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,8 +37,114 @@ class IndexOverflowJVMTest {
|
|||||||
override fun next(): Long = counter++
|
override fun next(): Long = counter++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun assertIndexOverflow(f: () -> Unit) {
|
||||||
|
val ex = assertFailsWith<ArithmeticException>(block = f)
|
||||||
|
assertTrue(ex.message!!.contains("index", ignoreCase = true))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun assertCountOverflow(f: () -> Unit) {
|
||||||
|
val ex = assertFailsWith<ArithmeticException>(block = f)
|
||||||
|
assertTrue(ex.message!!.contains("count", ignoreCase = true))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkIndexPositive(index: Int) {
|
||||||
|
if (index < 0) fail("Encountered negative index")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun indexOfOverflowSequence() {
|
||||||
|
assertIndexOverflow { maxIndexSequence.indexOf("j") }
|
||||||
|
assertIndexOverflow { maxIndexSequence.lastIndexOf("k") }
|
||||||
|
assertIndexOverflow { maxIndexSequence.indexOfFirst { false } }
|
||||||
|
assertIndexOverflow { maxIndexSequence.indexOfLast { false } }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun indexOfOverflowIterable() {
|
||||||
|
assertIndexOverflow { maxIndexIterable.indexOf("j") }
|
||||||
|
assertIndexOverflow { maxIndexIterable.lastIndexOf("k") }
|
||||||
|
assertIndexOverflow { maxIndexIterable.indexOfFirst { false } }
|
||||||
|
assertIndexOverflow { maxIndexIterable.indexOfLast { false } }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun forEachIndexedOverflow() {
|
||||||
|
assertIndexOverflow { maxIndexSequence.forEachIndexed { index, _ -> checkIndexPositive(index) } }
|
||||||
|
assertIndexOverflow { maxIndexIterable.forEachIndexed { index, _ -> checkIndexPositive(index) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun withIndexOverflow() {
|
||||||
|
assertIndexOverflow { maxIndexSequence.withIndex().forEach { (index, _) -> checkIndexPositive(index) } }
|
||||||
|
assertIndexOverflow { maxIndexIterable.withIndex().forEach { (index, _) -> checkIndexPositive(index) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun countOverflow() {
|
||||||
|
assertCountOverflow { repeatCounted("k").count() }
|
||||||
|
assertCountOverflow { repeatCounted("k").count { true } }
|
||||||
|
assertCountOverflow { repeatCounted("k").asIterable().count() }
|
||||||
|
assertCountOverflow { repeatCounted("k").asIterable().count { true } }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun averageCountOverflow() {
|
||||||
|
assertCountOverflow { repeatCounted(1.0).average() }
|
||||||
|
assertCountOverflow { repeatCounted(1L).asIterable().average() }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private class CountingCollection<T> : AbstractMutableCollection<T>() {
|
||||||
|
private var _size = 0
|
||||||
|
|
||||||
|
override fun add(element: T): Boolean {
|
||||||
|
if (_size < 0) error("Collection is too long")
|
||||||
|
_size++
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override val size: Int get() = _size
|
||||||
|
|
||||||
|
override fun iterator(): MutableIterator<T> = error("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun mapIndexedOverflow() {
|
||||||
|
assertIndexOverflow { maxIndexSequence.mapIndexed { index, _ -> checkIndexPositive(index) }.forEach { } }
|
||||||
|
assertIndexOverflow { maxIndexSequence.mapIndexedTo(CountingCollection()) { index, _ -> checkIndexPositive(index) } }
|
||||||
|
assertIndexOverflow { maxIndexIterable.mapIndexedTo(CountingCollection()) { index, _ -> checkIndexPositive(index) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun mapNotNullIndexedOverflow() {
|
||||||
|
assertIndexOverflow { maxIndexSequence.mapIndexedNotNull { index, _ -> checkIndexPositive(index) }.forEach { } }
|
||||||
|
assertIndexOverflow { maxIndexSequence.mapIndexedNotNullTo(CountingCollection()) { index, _ -> checkIndexPositive(index) } }
|
||||||
|
assertIndexOverflow { maxIndexIterable.mapIndexedNotNullTo(CountingCollection()) { index, _ -> checkIndexPositive(index) } }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun filterIndexedOverflow() {
|
||||||
|
assertIndexOverflow { maxIndexSequence.filterIndexed { index, _ -> checkIndexPositive(index); true }.forEach { } }
|
||||||
|
assertIndexOverflow { maxIndexSequence.filterIndexedTo(CountingCollection()) { index, _ -> checkIndexPositive(index); true } }
|
||||||
|
assertIndexOverflow { maxIndexIterable.filterIndexedTo(CountingCollection()) { index, _ -> checkIndexPositive(index); true } }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun foldIndexedOverflow() {
|
||||||
|
assertIndexOverflow { maxIndexSequence.foldIndexed("") { index, acc, s -> checkIndexPositive(index); s } }
|
||||||
|
assertIndexOverflow { maxIndexIterable.foldIndexed("") { index, acc, s -> checkIndexPositive(index); s } }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun reduceIndexedOverflow() {
|
||||||
|
assertIndexOverflow { maxIndexSequence.reduceIndexed { index, acc, s -> checkIndexPositive(index); s } }
|
||||||
|
assertIndexOverflow { maxIndexIterable.reduceIndexed { index, acc, s -> checkIndexPositive(index); s } }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -364,3 +364,20 @@ private fun rangeCheck(size: Int, fromIndex: Int, toIndex: Int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
internal expect fun checkIndexOverflow(index: Int): Int
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
internal expect fun checkCountOverflow(count: Int): Int
|
||||||
|
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
internal fun throwIndexOverflow() { throw ArithmeticException("Index overflow has happened.") }
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
internal fun throwCountOverflow() { throw ArithmeticException("Count overflow has happened.") }
|
||||||
|
|
||||||
|
|||||||
@@ -37,5 +37,5 @@ public inline fun <T> Iterator<T>.forEach(operation: (T) -> Unit): Unit {
|
|||||||
internal class IndexingIterator<out T>(private val iterator: Iterator<T>) : Iterator<IndexedValue<T>> {
|
internal class IndexingIterator<out T>(private val iterator: Iterator<T>) : Iterator<IndexedValue<T>> {
|
||||||
private var index = 0
|
private var index = 0
|
||||||
final override fun hasNext(): Boolean = iterator.hasNext()
|
final override fun hasNext(): Boolean = iterator.hasNext()
|
||||||
final override fun next(): IndexedValue<T> = IndexedValue(index++, iterator.next())
|
final override fun next(): IndexedValue<T> = IndexedValue(checkIndexOverflow(index++), iterator.next())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ constructor(private val sequence: Sequence<T>, private val transformer: (Int, T)
|
|||||||
val iterator = sequence.iterator()
|
val iterator = sequence.iterator()
|
||||||
var index = 0
|
var index = 0
|
||||||
override fun next(): R {
|
override fun next(): R {
|
||||||
return transformer(index++, iterator.next())
|
return transformer(checkIndexOverflow(index++), iterator.next())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean {
|
||||||
@@ -197,7 +197,7 @@ constructor(private val sequence: Sequence<T>) : Sequence<IndexedValue<T>> {
|
|||||||
val iterator = sequence.iterator()
|
val iterator = sequence.iterator()
|
||||||
var index = 0
|
var index = 0
|
||||||
override fun next(): IndexedValue<T> {
|
override fun next(): IndexedValue<T> {
|
||||||
return IndexedValue(index++, iterator.next())
|
return IndexedValue(checkIndexOverflow(index++), iterator.next())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
override fun hasNext(): Boolean {
|
||||||
|
|||||||
+2
@@ -2263,6 +2263,8 @@ public final class kotlin/collections/CollectionsKt {
|
|||||||
public static final fun takeLast (Ljava/util/List;I)Ljava/util/List;
|
public static final fun takeLast (Ljava/util/List;I)Ljava/util/List;
|
||||||
public static final fun takeLastWhile (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
|
public static final fun takeLastWhile (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
|
||||||
public static final fun takeWhile (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
|
public static final fun takeWhile (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
|
||||||
|
public static final fun throwCountOverflow ()V
|
||||||
|
public static final fun throwIndexOverflow ()V
|
||||||
public static final fun toBooleanArray (Ljava/util/Collection;)[Z
|
public static final fun toBooleanArray (Ljava/util/Collection;)[Z
|
||||||
public static final fun toByteArray (Ljava/util/Collection;)[B
|
public static final fun toByteArray (Ljava/util/Collection;)[B
|
||||||
public static final fun toCharArray (Ljava/util/Collection;)[C
|
public static final fun toCharArray (Ljava/util/Collection;)[C
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ object Aggregates : TemplateGroupBase() {
|
|||||||
doc { "Returns the number of ${f.element.pluralize()} matching the given [predicate]." }
|
doc { "Returns the number of ${f.element.pluralize()} matching the given [predicate]." }
|
||||||
returns("Int")
|
returns("Int")
|
||||||
body {
|
body {
|
||||||
|
fun checkOverflow(value: String) = if (f == Sequences || f == Iterables) "checkCountOverflow($value)" else value
|
||||||
"""
|
"""
|
||||||
${when (f) {
|
${when (f) {
|
||||||
Iterables -> "if (this is Collection && isEmpty()) return 0"
|
Iterables -> "if (this is Collection && isEmpty()) return 0"
|
||||||
@@ -162,7 +163,7 @@ object Aggregates : TemplateGroupBase() {
|
|||||||
else -> ""
|
else -> ""
|
||||||
}}
|
}}
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) if (predicate(element)) count++
|
for (element in this) if (predicate(element)) ${checkOverflow("++count")}
|
||||||
return count
|
return count
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
@@ -175,10 +176,11 @@ object Aggregates : TemplateGroupBase() {
|
|||||||
doc { "Returns the number of ${f.element.pluralize()} in this ${f.collection}." }
|
doc { "Returns the number of ${f.element.pluralize()} in this ${f.collection}." }
|
||||||
returns("Int")
|
returns("Int")
|
||||||
body {
|
body {
|
||||||
|
fun checkOverflow(value: String) = if (f == Sequences || f == Iterables) "checkCountOverflow($value)" else value
|
||||||
"""
|
"""
|
||||||
${if (f == Iterables) "if (this is Collection) return size" else ""}
|
${if (f == Iterables) "if (this is Collection) return size" else ""}
|
||||||
var count = 0
|
var count = 0
|
||||||
for (element in this) count++
|
for (element in this) ${checkOverflow("++count")}
|
||||||
return count
|
return count
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
@@ -474,10 +476,11 @@ object Aggregates : TemplateGroupBase() {
|
|||||||
typeParam("R")
|
typeParam("R")
|
||||||
returns("R")
|
returns("R")
|
||||||
body {
|
body {
|
||||||
|
fun checkOverflow(value: String) = if (f == Sequences || f == Iterables) "checkIndexOverflow($value)" else value
|
||||||
"""
|
"""
|
||||||
var index = 0
|
var index = 0
|
||||||
var accumulator = initial
|
var accumulator = initial
|
||||||
for (element in this) accumulator = operation(index++, accumulator, element)
|
for (element in this) accumulator = operation(${checkOverflow("index++")}, accumulator, element)
|
||||||
return accumulator
|
return accumulator
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
@@ -617,6 +620,7 @@ object Aggregates : TemplateGroupBase() {
|
|||||||
typeParam("T : S")
|
typeParam("T : S")
|
||||||
returns("S")
|
returns("S")
|
||||||
body {
|
body {
|
||||||
|
fun checkOverflow(value: String) = if (f == Sequences || f == Iterables) "checkIndexOverflow($value)" else value
|
||||||
"""
|
"""
|
||||||
val iterator = this.iterator()
|
val iterator = this.iterator()
|
||||||
if (!iterator.hasNext()) throw UnsupportedOperationException("Empty ${f.doc.collection} can't be reduced.")
|
if (!iterator.hasNext()) throw UnsupportedOperationException("Empty ${f.doc.collection} can't be reduced.")
|
||||||
@@ -624,7 +628,7 @@ object Aggregates : TemplateGroupBase() {
|
|||||||
var index = 1
|
var index = 1
|
||||||
var accumulator: S = iterator.next()
|
var accumulator: S = iterator.next()
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
accumulator = operation(index++, accumulator, iterator.next())
|
accumulator = operation(${checkOverflow("index++")}, accumulator, iterator.next())
|
||||||
}
|
}
|
||||||
return accumulator
|
return accumulator
|
||||||
"""
|
"""
|
||||||
@@ -899,9 +903,10 @@ object Aggregates : TemplateGroupBase() {
|
|||||||
""" }
|
""" }
|
||||||
returns("Unit")
|
returns("Unit")
|
||||||
body {
|
body {
|
||||||
|
fun checkOverflow(value: String) = if (f == Sequences || f == Iterables) "checkIndexOverflow($value)" else value
|
||||||
"""
|
"""
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) action(index++, item)
|
for (item in this) action(${checkOverflow("index++")}, item)
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ object Elements : TemplateGroupBase() {
|
|||||||
${if (f == Iterables) "if (this is List) return this.indexOf(element)" else ""}
|
${if (f == Iterables) "if (this is List) return this.indexOf(element)" else ""}
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) {
|
for (item in this) {
|
||||||
|
checkIndexOverflow(index)
|
||||||
if (element == item)
|
if (element == item)
|
||||||
return index
|
return index
|
||||||
index++
|
index++
|
||||||
@@ -106,6 +107,7 @@ object Elements : TemplateGroupBase() {
|
|||||||
var lastIndex = -1
|
var lastIndex = -1
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) {
|
for (item in this) {
|
||||||
|
checkIndexOverflow(index)
|
||||||
if (element == item)
|
if (element == item)
|
||||||
lastIndex = index
|
lastIndex = index
|
||||||
index++
|
index++
|
||||||
@@ -157,12 +159,13 @@ object Elements : TemplateGroupBase() {
|
|||||||
"""
|
"""
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) {
|
for (item in this) {
|
||||||
|
${if (f != Lists) "checkIndexOverflow(index)" else ""}
|
||||||
if (predicate(item))
|
if (predicate(item))
|
||||||
return index
|
return index
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
"""
|
""".lines().filterNot { it.isBlank() }.joinToString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
body(CharSequences, ArraysOfPrimitives, ArraysOfObjects) {
|
body(CharSequences, ArraysOfPrimitives, ArraysOfObjects) {
|
||||||
@@ -190,6 +193,7 @@ object Elements : TemplateGroupBase() {
|
|||||||
var lastIndex = -1
|
var lastIndex = -1
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this) {
|
for (item in this) {
|
||||||
|
checkIndexOverflow(index)
|
||||||
if (predicate(item))
|
if (predicate(item))
|
||||||
lastIndex = index
|
lastIndex = index
|
||||||
index++
|
index++
|
||||||
|
|||||||
@@ -204,10 +204,11 @@ object Mapping : TemplateGroupBase() {
|
|||||||
returns("C")
|
returns("C")
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
fun checkOverflow(value: String) = if (f == Sequences || f == Iterables) "checkIndexOverflow($value)" else value
|
||||||
"""
|
"""
|
||||||
var index = 0
|
var index = 0
|
||||||
for (item in this)
|
for (item in this)
|
||||||
destination.add(transform(index++, item))
|
destination.add(transform(${checkOverflow("index++")}, item))
|
||||||
return destination
|
return destination
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,12 +41,13 @@ object Numeric : TemplateGroupBase() {
|
|||||||
returns("Double")
|
returns("Double")
|
||||||
platformName("averageOf<T>")
|
platformName("averageOf<T>")
|
||||||
body {
|
body {
|
||||||
|
fun checkOverflow(value: String) = if (f == Family.Sequences || f == Family.Iterables) "checkCountOverflow($value)" else value
|
||||||
"""
|
"""
|
||||||
var sum: Double = 0.0
|
var sum: Double = 0.0
|
||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
for (element in this) {
|
for (element in this) {
|
||||||
sum += element
|
sum += element
|
||||||
count += 1
|
${checkOverflow("++count")}
|
||||||
}
|
}
|
||||||
return if (count == 0) Double.NaN else sum / count
|
return if (count == 0) Double.NaN else sum / count
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user