diff --git a/runtime/src/main/kotlin/kotlin/collections/AbstractList.kt b/runtime/src/main/kotlin/kotlin/collections/AbstractList.kt index 6454ab26565..35547f84260 100644 --- a/runtime/src/main/kotlin/kotlin/collections/AbstractList.kt +++ b/runtime/src/main/kotlin/kotlin/collections/AbstractList.kt @@ -137,4 +137,188 @@ public abstract class AbstractList protected constructor() : AbstractColl return true } } +} + + +/** + * AbstractMutableList implementation copied from JS backend + * (see js/js.libraries/src/core/collections/AbstractMutableList.kt). + * + * Based on GWT AbstractList + * Copyright 2007 Google Inc. + */ + +/** + * Provides a skeletal implementation of the [MutableList] interface. + * + * @param E the type of elements contained in the list. The list is invariant on its element type. + */ +public abstract class AbstractMutableList protected constructor() : AbstractMutableCollection(), MutableList { + protected var modCount: Int = 0 + + abstract override fun add(index: Int, element: E): Unit + abstract override fun removeAt(index: Int): E + abstract override fun set(index: Int, element: E): E + + override fun add(element: E): Boolean { + add(size, element) + return true + } + + override fun addAll(index: Int, elements: Collection): Boolean { + var i = index + var changed = false + for (e in elements) { + add(i++, e) + changed = true + } + return changed + } + + override fun clear() { + removeRange(0, size) + } + + override fun removeAll(elements: Collection): Boolean = removeAll { it in elements } + override fun retainAll(elements: Collection): Boolean = removeAll { it !in elements } + + + override fun iterator(): MutableIterator = IteratorImpl() + + override fun contains(element: E): Boolean = indexOf(element) >= 0 + + override fun indexOf(element: E): Int { + for (index in 0..lastIndex) { + if (get(index) == element) { + return index + } + } + return -1 + } + + override fun lastIndexOf(element: E): Int { + for (index in lastIndex downTo 0) { + if (get(index) == element) { + return index + } + } + return -1 + } + + override fun listIterator(): MutableListIterator = listIterator(0) + override fun listIterator(index: Int): MutableListIterator = ListIteratorImpl(index) + + + override fun subList(fromIndex: Int, toIndex: Int): MutableList = SubList(this, fromIndex, toIndex) + + /** + * Removes the range of elements from this list starting from [fromIndex] and ending with but not including [toIndex]. + */ + protected open fun removeRange(fromIndex: Int, toIndex: Int) { + val iterator = listIterator(fromIndex) + repeat(toIndex - fromIndex) { + iterator.next() + iterator.remove() + } + } + + private open inner class IteratorImpl : MutableIterator { + /** the index of the item that will be returned on the next call to [next]`()` */ + protected var index = 0 + /** the index of the item that was returned on the previous call to [next]`()` + * or [ListIterator.previous]`()` (for `ListIterator`), + * -1 if no such item exists + */ + protected var last = -1 + + override fun hasNext(): Boolean = index < size + + override fun next(): E { + if (!hasNext()) throw NoSuchElementException() + last = index++ + return get(last) + } + + override fun remove() { + check(last != -1) { "Call next() or previous() before removing element from the iterator."} + + removeAt(last) + index = last + last = -1 + } + } + + /** + * Implementation of `MutableListIterator` for abstract lists. + */ + private inner class ListIteratorImpl(index: Int) : IteratorImpl(), MutableListIterator { + + init { + AbstractList.checkPositionIndex(index, this@AbstractMutableList.size) + this.index = index + } + + override fun hasPrevious(): Boolean = index > 0 + + override fun nextIndex(): Int = index + + override fun previous(): E { + if (!hasPrevious()) throw NoSuchElementException() + + last = --index + return get(last) + } + + override fun previousIndex(): Int = index - 1 + + override fun add(element: E) { + add(index, element) + index++ + last = -1 + } + + override fun set(element: E) { + check(last != -1) { "Call next() or previous() before updating element value with the iterator."} + this@AbstractMutableList[last] = element + } + } + + private class SubList(private val list: AbstractMutableList, private val fromIndex: Int, toIndex: Int) : AbstractMutableList() { + private var _size: Int = 0 + + init { + AbstractList.checkRangeIndexes(fromIndex, toIndex, list.size) + this._size = toIndex - fromIndex + } + + override fun add(index: Int, element: E) { + AbstractList.checkPositionIndex(index, _size) + + list.add(fromIndex + index, element) + _size++ + } + + override fun get(index: Int): E { + AbstractList.checkElementIndex(index, _size) + + return list[fromIndex + index] + } + + override fun removeAt(index: Int): E { + AbstractList.checkElementIndex(index, _size) + + val result = list.removeAt(fromIndex + index) + _size-- + return result + } + + override fun set(index: Int, element: E): E { + AbstractList.checkElementIndex(index, _size) + + return list.set(fromIndex + index, element) + } + + override val size: Int get() = _size + } + } \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/collections/Collections.kt b/runtime/src/main/kotlin/kotlin/collections/Collections.kt index 049022ec5d5..557d19c70e2 100644 --- a/runtime/src/main/kotlin/kotlin/collections/Collections.kt +++ b/runtime/src/main/kotlin/kotlin/collections/Collections.kt @@ -338,7 +338,7 @@ public fun > List.binarySearch(element: T?, fromIndex: Int val comparisonResult = compareValues(middleValue, element) if (comparisonResult < 0) - low = middleIndex + 1 + lowBorder = middleIndex + 1 else if (comparisonResult > 0) highBorder = middleIndex - 1 else @@ -367,7 +367,7 @@ public fun List.binarySearch(element: T, comparator: Comparator, fr var lowBorder = fromIndex var highBorder = toIndex - 1 - while (lowBorder <= high) { + while (lowBorder <= highBorder) { val middleIndex = (lowBorder + highBorder).ushr(1) // safe from overflows val middleValue = get(middleIndex) val comparisonResult = comparator.compare(middleValue, element) @@ -375,7 +375,7 @@ public fun List.binarySearch(element: T, comparator: Comparator, fr if (comparisonResult < 0) lowBorder = middleIndex + 1 else if (comparisonResult > 0) - highBorderBorder = middleIndex - 1 + highBorder = middleIndex - 1 else return middleIndex // key found } diff --git a/runtime/src/main/kotlin/kotlin/collections/ReversedViews.kt b/runtime/src/main/kotlin/kotlin/collections/ReversedViews.kt index d2b93dedee1..6e80ffc75c3 100644 --- a/runtime/src/main/kotlin/kotlin/collections/ReversedViews.kt +++ b/runtime/src/main/kotlin/kotlin/collections/ReversedViews.kt @@ -21,7 +21,7 @@ private open class ReversedListReadOnly(private val delegate: List) : override fun get(index: Int): T = delegate[reverseElementIndex(index)] } -/* + private class ReversedList(private val delegate: MutableList) : AbstractMutableList() { override val size: Int get() = delegate.size override fun get(index: Int): T = delegate[reverseElementIndex(index)] @@ -33,7 +33,7 @@ private class ReversedList(private val delegate: MutableList) : AbstractMu override fun add(index: Int, element: T) { delegate.add(reversePositionIndex(index), element) } -}*/ +} private fun List<*>.reverseElementIndex(index: Int) = // TODO: Use AbstractList.checkElementIndex: run { AbstractList.checkElementIndex(index, size); lastIndex - index } if (index in 0..size - 1) size - index - 1 else throw IndexOutOfBoundsException("Index $index should be in range [${0..size - 1}].") @@ -46,10 +46,9 @@ private fun List<*>.reversePositionIndex(index: Int) = * All changes made in the original list will be reflected in the reversed one. */ public fun List.asReversed(): List = ReversedListReadOnly(this) -/* + /** * Returns a reversed mutable view of the original mutable List. * All changes made in the original list will be reflected in the reversed one and vice versa. */ public fun MutableList.asReversed(): MutableList = ReversedList(this) -*/ \ No newline at end of file