CollectionsKt.windowed throws IllegalArgumentException

This commit is contained in:
Abduqodiri Qurbonzoda
2019-09-16 20:34:13 +03:00
parent a7b984bcbf
commit d66f07a84e
6 changed files with 51 additions and 8 deletions
@@ -22,9 +22,10 @@ internal fun <T> Sequence<T>.windowedSequence(size: Int, step: Int, partialWindo
internal fun <T> windowedIterator(iterator: Iterator<T>, size: Int, step: Int, partialWindows: Boolean, reuseBuffer: Boolean): Iterator<List<T>> {
if (!iterator.hasNext()) return EmptyIterator
return iterator<List<T>> {
val bufferInitialCapacity = size.coerceAtMost(1024)
val gap = step - size
if (gap >= 0) {
var buffer = ArrayList<T>(size)
var buffer = ArrayList<T>(bufferInitialCapacity)
var skip = 0
for (e in iterator) {
if (skip > 0) { skip -= 1; continue }
@@ -39,10 +40,12 @@ internal fun <T> windowedIterator(iterator: Iterator<T>, size: Int, step: Int, p
if (partialWindows || buffer.size == size) yield(buffer)
}
} else {
val buffer = RingBuffer<T>(size)
var buffer = RingBuffer<T>(bufferInitialCapacity)
for (e in iterator) {
buffer.add(e)
if (buffer.isFull()) {
if (buffer.size < size) { buffer = buffer.expanded(maxCapacity = size); continue }
yield(if (reuseBuffer) buffer else ArrayList(buffer))
buffer.removeFirst(step)
}
@@ -83,15 +86,18 @@ internal class MovingSubList<out E>(private val list: List<E>) : AbstractList<E>
*
* Buffer overflow is not allowed so [add] doesn't overwrite tail but raises an exception.
*/
private class RingBuffer<T>(val capacity: Int) : AbstractList<T>(), RandomAccess {
private class RingBuffer<T>(private val buffer: Array<Any?>, filledSize: Int) : AbstractList<T>(), RandomAccess {
init {
require(capacity >= 0) { "ring buffer capacity should not be negative but it is $capacity" }
require(filledSize >= 0) { "ring buffer filled size should not be negative but it is $filledSize" }
require(filledSize <= buffer.size) { "ring buffer filled size: $filledSize cannot be larger than the buffer size: ${buffer.size}" }
}
private val buffer = arrayOfNulls<Any?>(capacity)
constructor(capacity: Int) : this(arrayOfNulls<Any?>(capacity), 0)
private val capacity = buffer.size
private var startIndex: Int = 0
override var size: Int = 0
override var size: Int = filledSize
private set
override fun get(index: Int): T {
@@ -149,6 +155,16 @@ private class RingBuffer<T>(val capacity: Int) : AbstractList<T>(), RandomAccess
return toArray(arrayOfNulls(size))
}
/**
* Creates a new ring buffer with the capacity equal to the minimum of [maxCapacity] and 1.5 * [capacity].
* The returned ring buffer contains the same elements as this ring buffer.
*/
fun expanded(maxCapacity: Int): RingBuffer<T> {
val newCapacity = (capacity + (capacity shr 1) + 1).coerceAtMost(maxCapacity)
val newBuffer = if (startIndex == 0) buffer.copyOf(newCapacity) else toArray(arrayOfNulls(newCapacity))
return RingBuffer(newBuffer, size)
}
/**
* Add [element] to the buffer or fail with [IllegalStateException] if no free space available in the buffer
*/