Decommonize collection builder implementations
This commit is contained in:
@@ -49,22 +49,75 @@ internal actual fun <T> copyToArrayImpl(collection: Collection<*>, array: Array<
|
||||
return array
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing only the specified object [element].
|
||||
*/
|
||||
public fun <T> listOf(element: T): List<T> = arrayListOf(element)
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <E> buildListInternal(builderAction: MutableList<E>.() -> Unit): List<E> {
|
||||
return ArrayList<E>().apply(builderAction).build()
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <E> buildListInternal(capacity: Int, builderAction: MutableList<E>.() -> Unit): List<E> {
|
||||
checkBuilderCapacity(capacity)
|
||||
return ArrayList<E>(capacity).apply(builderAction).build()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing only the specified object [element].
|
||||
*/
|
||||
public fun <T> setOf(element: T): Set<T> = hashSetOf(element)
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <E> buildSetInternal(builderAction: MutableSet<E>.() -> Unit): Set<E> {
|
||||
return LinkedHashSet<E>().apply(builderAction).build()
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <E> buildSetInternal(capacity: Int, builderAction: MutableSet<E>.() -> Unit): Set<E> {
|
||||
return LinkedHashSet<E>(capacity).apply(builderAction).build()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an immutable map, mapping only the specified key to the
|
||||
* specified value.
|
||||
*/
|
||||
public fun <K, V> mapOf(pair: Pair<K, V>): Map<K, V> = hashMapOf(pair)
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <K, V> buildMapInternal(builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> {
|
||||
return LinkedHashMap<K, V>().apply(builderAction).build()
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <K, V> buildMapInternal(capacity: Int, builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> {
|
||||
return LinkedHashMap<K, V>(capacity).apply(builderAction).build()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fills the list with the provided [value].
|
||||
*
|
||||
@@ -196,6 +249,6 @@ internal actual fun mapCapacity(expectedSize: Int) = expectedSize
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@PublishedApi
|
||||
internal actual fun checkBuilderCapacity(capacity: Int) {
|
||||
internal fun checkBuilderCapacity(capacity: Int) {
|
||||
require(capacity >= 0) { "capacity must be non-negative." }
|
||||
}
|
||||
@@ -15,6 +15,7 @@ public actual abstract class AbstractMutableCollection<E> protected actual const
|
||||
actual abstract override fun add(element: E): Boolean
|
||||
|
||||
actual override fun remove(element: E): Boolean {
|
||||
checkIsMutable()
|
||||
val iterator = iterator()
|
||||
while (iterator.hasNext()) {
|
||||
if (iterator.next() == element) {
|
||||
@@ -26,6 +27,7 @@ public actual abstract class AbstractMutableCollection<E> protected actual const
|
||||
}
|
||||
|
||||
actual override fun addAll(elements: Collection<E>): Boolean {
|
||||
checkIsMutable()
|
||||
var modified = false
|
||||
for (element in elements) {
|
||||
if (add(element)) modified = true
|
||||
@@ -33,10 +35,18 @@ public actual abstract class AbstractMutableCollection<E> protected actual const
|
||||
return modified
|
||||
}
|
||||
|
||||
actual override fun removeAll(elements: Collection<E>): Boolean = (this as MutableIterable<E>).removeAll { it in elements }
|
||||
actual override fun retainAll(elements: Collection<E>): Boolean = (this as MutableIterable<E>).removeAll { it !in elements }
|
||||
actual override fun removeAll(elements: Collection<E>): Boolean {
|
||||
checkIsMutable()
|
||||
return (this as MutableIterable<E>).removeAll { it in elements }
|
||||
}
|
||||
|
||||
actual override fun retainAll(elements: Collection<E>): Boolean {
|
||||
checkIsMutable()
|
||||
return (this as MutableIterable<E>).removeAll { it !in elements }
|
||||
}
|
||||
|
||||
actual override fun clear(): Unit {
|
||||
checkIsMutable()
|
||||
val iterator = this.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
iterator.next()
|
||||
@@ -46,5 +56,12 @@ public actual abstract class AbstractMutableCollection<E> protected actual const
|
||||
|
||||
@JsName("toJSON")
|
||||
open fun toJSON(): Any = this.toArray()
|
||||
|
||||
|
||||
/**
|
||||
* This method is called every time when a mutating method is called on this mutable collection.
|
||||
* Mutable collections that are built (frozen) must throw `UnsupportedOperationException`.
|
||||
*/
|
||||
internal open fun checkIsMutable(): Unit { }
|
||||
}
|
||||
|
||||
|
||||
@@ -28,11 +28,13 @@ public actual abstract class AbstractMutableList<E> protected actual constructor
|
||||
* @return `true` because the list is always modified as the result of this operation.
|
||||
*/
|
||||
actual override fun add(element: E): Boolean {
|
||||
checkIsMutable()
|
||||
add(size, element)
|
||||
return true
|
||||
}
|
||||
|
||||
actual override fun addAll(index: Int, elements: Collection<E>): Boolean {
|
||||
checkIsMutable()
|
||||
var _index = index
|
||||
var changed = false
|
||||
for (e in elements) {
|
||||
@@ -43,11 +45,19 @@ public actual abstract class AbstractMutableList<E> protected actual constructor
|
||||
}
|
||||
|
||||
actual override fun clear() {
|
||||
checkIsMutable()
|
||||
removeRange(0, size)
|
||||
}
|
||||
|
||||
actual override fun removeAll(elements: Collection<E>): Boolean = removeAll { it in elements }
|
||||
actual override fun retainAll(elements: Collection<E>): Boolean = removeAll { it !in elements }
|
||||
actual override fun removeAll(elements: Collection<E>): Boolean {
|
||||
checkIsMutable()
|
||||
return removeAll { it in elements }
|
||||
}
|
||||
|
||||
actual override fun retainAll(elements: Collection<E>): Boolean {
|
||||
checkIsMutable()
|
||||
return removeAll { it !in elements }
|
||||
}
|
||||
|
||||
|
||||
actual override fun iterator(): MutableIterator<E> = IteratorImpl()
|
||||
@@ -164,7 +174,7 @@ public actual abstract class AbstractMutableList<E> protected actual constructor
|
||||
|
||||
override fun set(element: E) {
|
||||
check(last != -1) { "Call next() or previous() before updating element value with the iterator." }
|
||||
this@AbstractMutableList[last] = element
|
||||
set(last, element)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,6 +214,8 @@ public actual abstract class AbstractMutableList<E> protected actual constructor
|
||||
}
|
||||
|
||||
override val size: Int get() = _size
|
||||
|
||||
internal override fun checkIsMutable(): Unit = list.checkIsMutable()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
|
||||
override val value: V get() = _value
|
||||
|
||||
override fun setValue(newValue: V): V {
|
||||
// Should check if the map containing this entry is mutable.
|
||||
// However, to not increase entry memory footprint it might be worthwhile not to check it here and
|
||||
// force subclasses that implement `build()` (freezing) operation to implement their own `MutableEntry`.
|
||||
// this@AbstractMutableMap.checkIsMutable()
|
||||
val oldValue = this._value
|
||||
this._value = newValue
|
||||
return oldValue
|
||||
@@ -67,6 +71,7 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
|
||||
}
|
||||
|
||||
override fun remove(element: K): Boolean {
|
||||
checkIsMutable()
|
||||
if (containsKey(element)) {
|
||||
this@AbstractMutableMap.remove(element)
|
||||
return true
|
||||
@@ -75,6 +80,8 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
|
||||
}
|
||||
|
||||
override val size: Int get() = this@AbstractMutableMap.size
|
||||
|
||||
override fun checkIsMutable(): Unit = this@AbstractMutableMap.checkIsMutable()
|
||||
}
|
||||
}
|
||||
return _keys!!
|
||||
@@ -83,6 +90,7 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
|
||||
actual abstract override fun put(key: K, value: V): V?
|
||||
|
||||
actual override fun putAll(from: Map<out K, V>) {
|
||||
checkIsMutable()
|
||||
for ((key, value) in from) {
|
||||
put(key, value)
|
||||
}
|
||||
@@ -117,12 +125,15 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = AbstractList.orderedHashCode(this)
|
||||
|
||||
override fun checkIsMutable(): Unit = this@AbstractMutableMap.checkIsMutable()
|
||||
}
|
||||
}
|
||||
return _values!!
|
||||
}
|
||||
|
||||
actual override fun remove(key: K): V? {
|
||||
checkIsMutable()
|
||||
val iter = entries.iterator()
|
||||
while (iter.hasNext()) {
|
||||
val entry = iter.next()
|
||||
@@ -136,4 +147,10 @@ public actual abstract class AbstractMutableMap<K, V> protected actual construct
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is called every time when a mutating method is called on this mutable map.
|
||||
* Mutable maps that are built (frozen) must throw `UnsupportedOperationException`.
|
||||
*/
|
||||
internal open fun checkIsMutable(): Unit {}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ package kotlin.collections
|
||||
* capacity and "growth increment" concepts.
|
||||
*/
|
||||
public actual open class ArrayList<E> internal constructor(private var array: Array<Any?>) : AbstractMutableList<E>(), MutableList<E>, RandomAccess {
|
||||
private var isReadOnly: Boolean = false
|
||||
|
||||
/**
|
||||
* Creates an empty [ArrayList].
|
||||
@@ -31,6 +32,13 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
|
||||
*/
|
||||
public actual constructor(elements: Collection<E>) : this(elements.toTypedArray<Any?>()) {}
|
||||
|
||||
@PublishedApi
|
||||
internal fun build(): List<E> {
|
||||
checkIsMutable()
|
||||
isReadOnly = true
|
||||
return this
|
||||
}
|
||||
|
||||
/** Does nothing in this ArrayList implementation. */
|
||||
public actual fun trimToSize() {}
|
||||
|
||||
@@ -41,23 +49,27 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
actual override fun get(index: Int): E = array[rangeCheck(index)] as E
|
||||
actual override fun set(index: Int, element: E): E {
|
||||
checkIsMutable()
|
||||
rangeCheck(index)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return array[index].apply { array[index] = element } as E
|
||||
}
|
||||
|
||||
actual override fun add(element: E): Boolean {
|
||||
checkIsMutable()
|
||||
array.asDynamic().push(element)
|
||||
modCount++
|
||||
return true
|
||||
}
|
||||
|
||||
actual override fun add(index: Int, element: E): Unit {
|
||||
checkIsMutable()
|
||||
array.asDynamic().splice(insertionRangeCheck(index), 0, element)
|
||||
modCount++
|
||||
}
|
||||
|
||||
actual override fun addAll(elements: Collection<E>): Boolean {
|
||||
checkIsMutable()
|
||||
if (elements.isEmpty()) return false
|
||||
|
||||
array += elements.toTypedArray<Any?>()
|
||||
@@ -66,6 +78,7 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
|
||||
}
|
||||
|
||||
actual override fun addAll(index: Int, elements: Collection<E>): Boolean {
|
||||
checkIsMutable()
|
||||
insertionRangeCheck(index)
|
||||
|
||||
if (index == size) return addAll(elements)
|
||||
@@ -81,6 +94,7 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
|
||||
}
|
||||
|
||||
actual override fun removeAt(index: Int): E {
|
||||
checkIsMutable()
|
||||
rangeCheck(index)
|
||||
modCount++
|
||||
return if (index == lastIndex)
|
||||
@@ -90,6 +104,7 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
|
||||
}
|
||||
|
||||
actual override fun remove(element: E): Boolean {
|
||||
checkIsMutable()
|
||||
for (index in array.indices) {
|
||||
if (array[index] == element) {
|
||||
array.asDynamic().splice(index, 1)
|
||||
@@ -101,11 +116,13 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
|
||||
}
|
||||
|
||||
override fun removeRange(fromIndex: Int, toIndex: Int) {
|
||||
checkIsMutable()
|
||||
modCount++
|
||||
array.asDynamic().splice(fromIndex, toIndex - fromIndex)
|
||||
}
|
||||
|
||||
actual override fun clear() {
|
||||
checkIsMutable()
|
||||
array = emptyArray()
|
||||
modCount++
|
||||
}
|
||||
@@ -119,6 +136,10 @@ public actual open class ArrayList<E> internal constructor(private var array: Ar
|
||||
override fun toArray(): Array<Any?> = js("[]").slice.call(array)
|
||||
|
||||
|
||||
internal override fun checkIsMutable() {
|
||||
if (isReadOnly) throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
private fun rangeCheck(index: Int) = index.apply {
|
||||
AbstractList.checkElementIndex(index, size)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ import kotlin.collections.MutableMap.MutableEntry
|
||||
*
|
||||
* This implementation makes no guarantees regarding the order of enumeration of [keys], [values] and [entries] collections.
|
||||
*/
|
||||
// Classes that extend HashMap and implement `build()` (freezing) operation
|
||||
// have to make sure mutating methods check `checkIsMutable`.
|
||||
public actual open class HashMap<K, V> : AbstractMutableMap<K, V>, MutableMap<K, V> {
|
||||
|
||||
private inner class EntrySet : AbstractMutableSet<MutableEntry<K, V>>() {
|
||||
|
||||
@@ -12,9 +12,11 @@ package kotlin.collections
|
||||
/**
|
||||
* The implementation of the [MutableSet] interface, backed by a [HashMap] instance.
|
||||
*/
|
||||
// Classes that extend HashSet and implement `build()` (freezing) operation
|
||||
// have to make sure mutating methods check `checkIsMutable`.
|
||||
public actual open class HashSet<E> : AbstractMutableSet<E>, MutableSet<E> {
|
||||
|
||||
private val map: HashMap<E, Any>
|
||||
internal val map: HashMap<E, Any>
|
||||
|
||||
/**
|
||||
* Constructs a new empty [HashSet].
|
||||
|
||||
@@ -30,9 +30,14 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
|
||||
* small modifications. Paying a small storage cost only if you use
|
||||
* LinkedHashMap and minimizing code size seemed like a better tradeoff
|
||||
*/
|
||||
private class ChainEntry<K, V>(key: K, value: V) : AbstractMutableMap.SimpleEntry<K, V>(key, value) {
|
||||
private inner class ChainEntry<K, V>(key: K, value: V) : AbstractMutableMap.SimpleEntry<K, V>(key, value) {
|
||||
internal var next: ChainEntry<K, V>? = null
|
||||
internal var prev: ChainEntry<K, V>? = null
|
||||
|
||||
override fun setValue(newValue: V): V {
|
||||
this@LinkedHashMap.checkIsMutable()
|
||||
return super.setValue(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class EntrySet : AbstractMutableSet<MutableEntry<K, V>>() {
|
||||
@@ -65,6 +70,7 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
|
||||
|
||||
override fun remove() {
|
||||
check(last != null)
|
||||
this@EntrySet.checkIsMutable()
|
||||
// checkStructuralChange(map, this)
|
||||
|
||||
last!!.remove()
|
||||
@@ -84,6 +90,7 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
|
||||
override operator fun iterator(): MutableIterator<MutableEntry<K, V>> = EntryIterator()
|
||||
|
||||
override fun remove(element: MutableEntry<K, V>): Boolean {
|
||||
checkIsMutable()
|
||||
if (contains(element)) {
|
||||
this@LinkedHashMap.remove(element.key)
|
||||
return true
|
||||
@@ -92,6 +99,8 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
|
||||
}
|
||||
|
||||
override val size: Int get() = this@LinkedHashMap.size
|
||||
|
||||
override fun checkIsMutable(): Unit = this@LinkedHashMap.checkIsMutable()
|
||||
}
|
||||
|
||||
|
||||
@@ -154,6 +163,8 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
|
||||
*/
|
||||
private val map: HashMap<K, ChainEntry<K, V>>
|
||||
|
||||
private var isReadOnly: Boolean = false
|
||||
|
||||
/**
|
||||
* Constructs an empty [LinkedHashMap] instance.
|
||||
*/
|
||||
@@ -189,7 +200,15 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
|
||||
this.putAll(original)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun build(): Map<K, V> {
|
||||
checkIsMutable()
|
||||
isReadOnly = true
|
||||
return this
|
||||
}
|
||||
|
||||
actual override fun clear() {
|
||||
checkIsMutable()
|
||||
map.clear()
|
||||
head = null
|
||||
}
|
||||
@@ -219,6 +238,8 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
|
||||
actual override operator fun get(key: K): V? = map.get(key)?.value
|
||||
|
||||
actual override fun put(key: K, value: V): V? {
|
||||
checkIsMutable()
|
||||
|
||||
val old = map.get(key)
|
||||
if (old == null) {
|
||||
val newEntry = ChainEntry(key, value)
|
||||
@@ -231,6 +252,8 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
|
||||
}
|
||||
|
||||
actual override fun remove(key: K): V? {
|
||||
checkIsMutable()
|
||||
|
||||
val entry = map.remove(key)
|
||||
if (entry != null) {
|
||||
entry.remove()
|
||||
@@ -241,6 +264,9 @@ public actual open class LinkedHashMap<K, V> : HashMap<K, V>, MutableMap<K, V> {
|
||||
|
||||
actual override val size: Int get() = map.size
|
||||
|
||||
internal override fun checkIsMutable() {
|
||||
if (isReadOnly) throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,6 +43,14 @@ public actual open class LinkedHashSet<E> : HashSet<E>, MutableSet<E> {
|
||||
|
||||
actual constructor(initialCapacity: Int) : this(initialCapacity, 0.0f)
|
||||
|
||||
@PublishedApi
|
||||
internal fun build(): Set<E> {
|
||||
(map as LinkedHashMap<E, Any>).build()
|
||||
return this
|
||||
}
|
||||
|
||||
internal override fun checkIsMutable(): Unit = map.checkIsMutable()
|
||||
|
||||
// public override fun clone(): Any {
|
||||
// return LinkedHashSet(this)
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user