stdlib: Add AbstractMutableList implementation

The implementation is based on the AbstractMutableList class
of JS backend.
This commit is contained in:
Ilya Matveev
2017-04-18 12:46:00 +07:00
committed by ilmat192
parent 9da229896b
commit fcece669ec
3 changed files with 190 additions and 7 deletions
@@ -137,4 +137,188 @@ public abstract class AbstractList<out E> protected constructor() : AbstractColl
return true
}
}
}
/**
* AbstractMutableList implementation copied from JS backend
* (see <Kotlin JVM root>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<E> protected constructor() : AbstractMutableCollection<E>(), MutableList<E> {
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<E>): 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<E>): Boolean = removeAll { it in elements }
override fun retainAll(elements: Collection<E>): Boolean = removeAll { it !in elements }
override fun iterator(): MutableIterator<E> = 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<E> = listIterator(0)
override fun listIterator(index: Int): MutableListIterator<E> = ListIteratorImpl(index)
override fun subList(fromIndex: Int, toIndex: Int): MutableList<E> = 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<E> {
/** 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<E> {
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<E>(private val list: AbstractMutableList<E>, private val fromIndex: Int, toIndex: Int) : AbstractMutableList<E>() {
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
}
}
@@ -338,7 +338,7 @@ public fun <T: Comparable<T>> List<T?>.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 <T> List<T>.binarySearch(element: T, comparator: Comparator<in T>, 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 <T> List<T>.binarySearch(element: T, comparator: Comparator<in T>, fr
if (comparisonResult < 0)
lowBorder = middleIndex + 1
else if (comparisonResult > 0)
highBorderBorder = middleIndex - 1
highBorder = middleIndex - 1
else
return middleIndex // key found
}
@@ -21,7 +21,7 @@ private open class ReversedListReadOnly<out T>(private val delegate: List<T>) :
override fun get(index: Int): T = delegate[reverseElementIndex(index)]
}
/*
private class ReversedList<T>(private val delegate: MutableList<T>) : AbstractMutableList<T>() {
override val size: Int get() = delegate.size
override fun get(index: Int): T = delegate[reverseElementIndex(index)]
@@ -33,7 +33,7 @@ private class ReversedList<T>(private val delegate: MutableList<T>) : 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 <T> List<T>.asReversed(): List<T> = 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 <T> MutableList<T>.asReversed(): MutableList<T> = ReversedList(this)
*/