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)
|
||||
// }
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
import kotlin.collections.builders.ListBuilder
|
||||
import kotlin.internal.InlineOnly
|
||||
import kotlin.internal.apiVersionIsAtLeast
|
||||
|
||||
@@ -18,6 +19,42 @@ import kotlin.internal.apiVersionIsAtLeast
|
||||
*/
|
||||
public fun <T> listOf(element: T): List<T> = java.util.Collections.singletonList(element)
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <E> buildListInternal(builderAction: MutableList<E>.() -> Unit): List<E> {
|
||||
return build(createListBuilder<E>().apply(builderAction))
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <E> buildListInternal(capacity: Int, builderAction: MutableList<E>.() -> Unit): List<E> {
|
||||
return build(createListBuilder<E>(capacity).apply(builderAction))
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
internal fun <E> createListBuilder(): MutableList<E> {
|
||||
return ListBuilder<E>()
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
internal fun <E> createListBuilder(capacity: Int): MutableList<E> {
|
||||
return ListBuilder<E>(capacity)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
internal fun <E> build(builder: MutableList<E>): List<E> {
|
||||
return (builder as ListBuilder<E>).build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list containing the elements returned by this enumeration
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
package kotlin.collections
|
||||
|
||||
import java.util.Comparator
|
||||
import java.util.LinkedHashMap
|
||||
import java.util.Properties
|
||||
import java.util.SortedMap
|
||||
import java.util.TreeMap
|
||||
import java.util.concurrent.ConcurrentMap
|
||||
import kotlin.collections.builders.MapBuilder
|
||||
|
||||
|
||||
/**
|
||||
@@ -26,6 +26,43 @@ import java.util.concurrent.ConcurrentMap
|
||||
*/
|
||||
public fun <K, V> mapOf(pair: Pair<K, V>): Map<K, V> = java.util.Collections.singletonMap(pair.first, pair.second)
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <K, V> buildMapInternal(builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> {
|
||||
return build(createMapBuilder<K, V>().apply(builderAction))
|
||||
}
|
||||
|
||||
@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 build(createMapBuilder<K, V>(capacity).apply(builderAction))
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
internal fun <K, V> createMapBuilder(): MutableMap<K, V> {
|
||||
return MapBuilder()
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
internal fun <K, V> createMapBuilder(capacity: Int): MutableMap<K, V> {
|
||||
return MapBuilder(capacity)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
internal fun <K, V> build(builder: MutableMap<K, V>): Map<K, V> {
|
||||
return (builder as MapBuilder<K, V>).build()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Concurrent getOrPut, that is safe for concurrent maps.
|
||||
@@ -111,13 +148,3 @@ internal actual fun mapCapacity(expectedSize: Int): Int = when {
|
||||
else -> Int.MAX_VALUE
|
||||
}
|
||||
private const val INT_MAX_POWER_OF_TWO: Int = 1 shl (Int.SIZE_BITS - 2)
|
||||
|
||||
/**
|
||||
* Checks a collection builder function capacity argument.
|
||||
* Does nothing, capacity is validated in List/Set/Map constructor
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@PublishedApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun checkBuilderCapacity(capacity: Int) {}
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
import kotlin.collections.builders.SetBuilder
|
||||
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing only the specified object [element].
|
||||
@@ -15,6 +17,43 @@ package kotlin.collections
|
||||
*/
|
||||
public fun <T> setOf(element: T): Set<T> = java.util.Collections.singleton(element)
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <E> buildSetInternal(builderAction: MutableSet<E>.() -> Unit): Set<E> {
|
||||
return build(createSetBuilder<E>().apply(builderAction))
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal actual inline fun <E> buildSetInternal(capacity: Int, builderAction: MutableSet<E>.() -> Unit): Set<E> {
|
||||
return build(createSetBuilder<E>(capacity).apply(builderAction))
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
internal fun <E> createSetBuilder(): MutableSet<E> {
|
||||
return SetBuilder()
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
internal fun <E> createSetBuilder(capacity: Int): MutableSet<E> {
|
||||
return SetBuilder(capacity)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
internal fun <E> build(builder: MutableSet<E>): Set<E> {
|
||||
return (builder as SetBuilder<E>).build()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new [java.util.SortedSet] with the given elements.
|
||||
|
||||
+6
-7
@@ -5,19 +5,19 @@
|
||||
|
||||
package kotlin.collections.builders
|
||||
|
||||
@PublishedApi
|
||||
internal class ListBuilder<E> private constructor(
|
||||
private var array: Array<E>,
|
||||
private var offset: Int,
|
||||
private var length: Int,
|
||||
private var isReadOnly: Boolean,
|
||||
private val backing: ListBuilder<E>?
|
||||
private val backing: ListBuilder<E>?,
|
||||
private val root: ListBuilder<E>?
|
||||
) : MutableList<E>, RandomAccess, AbstractMutableList<E>() {
|
||||
|
||||
constructor() : this(10)
|
||||
|
||||
constructor(initialCapacity: Int) : this(
|
||||
arrayOfUninitializedElements(initialCapacity), 0, 0, false, null)
|
||||
arrayOfUninitializedElements(initialCapacity), 0, 0, false, null, null)
|
||||
|
||||
fun build(): List<E> {
|
||||
if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ListBuilder
|
||||
@@ -127,7 +127,7 @@ internal class ListBuilder<E> private constructor(
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int): MutableList<E> {
|
||||
AbstractList.checkRangeIndexes(fromIndex, toIndex, length)
|
||||
return ListBuilder(array, offset + fromIndex, toIndex - fromIndex, isReadOnly, this)
|
||||
return ListBuilder(array, offset + fromIndex, toIndex - fromIndex, isReadOnly, this, root ?: this)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
@@ -155,7 +155,7 @@ internal class ListBuilder<E> private constructor(
|
||||
// ---------------------------- private ----------------------------
|
||||
|
||||
private fun checkIsMutable() {
|
||||
if (isReadOnly) throw UnsupportedOperationException()
|
||||
if (isReadOnly || root != null && root.isReadOnly) throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
private fun ensureExtraCapacity(n: Int) {
|
||||
@@ -277,9 +277,8 @@ internal class ListBuilder<E> private constructor(
|
||||
}
|
||||
|
||||
override fun set(element: E) {
|
||||
list.checkIsMutable()
|
||||
check(lastIndex != -1) { "Call next() or previous() before replacing element from the iterator." }
|
||||
list.array[list.offset + lastIndex] = element
|
||||
list.set(lastIndex, element)
|
||||
}
|
||||
|
||||
override fun add(element: E) {
|
||||
+46
-18
@@ -5,7 +5,6 @@
|
||||
|
||||
package kotlin.collections.builders
|
||||
|
||||
@PublishedApi
|
||||
internal class MapBuilder<K, V> private constructor(
|
||||
private var keysArray: Array<K>,
|
||||
private var valuesArray: Array<V>?, // allocated only when actually used, always null in pure HashSet
|
||||
@@ -19,9 +18,9 @@ internal class MapBuilder<K, V> private constructor(
|
||||
override var size: Int = 0
|
||||
private set
|
||||
|
||||
private var keysView: HashMapKeys<K>? = null
|
||||
private var valuesView: HashMapValues<V>? = null
|
||||
private var entriesView: HashMapEntrySet<K, V>? = null
|
||||
private var keysView: MapBuilderKeys<K>? = null
|
||||
private var valuesView: MapBuilderValues<V>? = null
|
||||
private var entriesView: MapBuilderEntries<K, V>? = null
|
||||
|
||||
private var isReadOnly: Boolean = false
|
||||
|
||||
@@ -68,7 +67,8 @@ internal class MapBuilder<K, V> private constructor(
|
||||
}
|
||||
|
||||
override fun putAll(from: Map<out K, V>) {
|
||||
putAllEntries(from.entries) // mutability gets checked here
|
||||
checkIsMutable()
|
||||
putAllEntries(from.entries)
|
||||
}
|
||||
|
||||
override fun remove(key: K): V? {
|
||||
@@ -99,7 +99,7 @@ internal class MapBuilder<K, V> private constructor(
|
||||
override val keys: MutableSet<K> get() {
|
||||
val cur = keysView
|
||||
return if (cur == null) {
|
||||
val new = HashMapKeys(this)
|
||||
val new = MapBuilderKeys(this)
|
||||
keysView = new
|
||||
new
|
||||
} else cur
|
||||
@@ -108,7 +108,7 @@ internal class MapBuilder<K, V> private constructor(
|
||||
override val values: MutableCollection<V> get() {
|
||||
val cur = valuesView
|
||||
return if (cur == null) {
|
||||
val new = HashMapValues(this)
|
||||
val new = MapBuilderValues(this)
|
||||
valuesView = new
|
||||
new
|
||||
} else cur
|
||||
@@ -117,7 +117,7 @@ internal class MapBuilder<K, V> private constructor(
|
||||
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> get() {
|
||||
val cur = entriesView
|
||||
return if (cur == null) {
|
||||
val new = HashMapEntrySet(this)
|
||||
val new = MapBuilderEntries(this)
|
||||
entriesView = new
|
||||
return new
|
||||
} else cur
|
||||
@@ -157,7 +157,7 @@ internal class MapBuilder<K, V> private constructor(
|
||||
private val capacity: Int get() = keysArray.size
|
||||
private val hashSize: Int get() = hashArray.size
|
||||
|
||||
private fun checkIsMutable() {
|
||||
internal fun checkIsMutable() {
|
||||
if (isReadOnly) throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
@@ -382,8 +382,7 @@ internal class MapBuilder<K, V> private constructor(
|
||||
return true
|
||||
}
|
||||
|
||||
internal fun putEntry(entry: Map.Entry<K, V>): Boolean {
|
||||
checkIsMutable()
|
||||
private fun putEntry(entry: Map.Entry<K, V>): Boolean {
|
||||
val index = addKey(entry.key)
|
||||
val valuesArray = allocateValuesArray()
|
||||
if (index >= 0) {
|
||||
@@ -398,8 +397,7 @@ internal class MapBuilder<K, V> private constructor(
|
||||
return false
|
||||
}
|
||||
|
||||
internal fun putAllEntries(from: Collection<Map.Entry<K, V>>): Boolean {
|
||||
checkIsMutable()
|
||||
private fun putAllEntries(from: Collection<Map.Entry<K, V>>): Boolean {
|
||||
if (from.isEmpty()) return false
|
||||
ensureExtraCapacity(from.size)
|
||||
val it = from.iterator()
|
||||
@@ -549,7 +547,7 @@ internal class MapBuilder<K, V> private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
internal class HashMapKeys<E> internal constructor(
|
||||
internal class MapBuilderKeys<E> internal constructor(
|
||||
private val backing: MapBuilder<E, *>
|
||||
) : MutableSet<E>, AbstractMutableSet<E>() {
|
||||
|
||||
@@ -561,9 +559,19 @@ internal class HashMapKeys<E> internal constructor(
|
||||
override fun addAll(elements: Collection<E>): Boolean = throw UnsupportedOperationException()
|
||||
override fun remove(element: E): Boolean = backing.removeKey(element) >= 0
|
||||
override fun iterator(): MutableIterator<E> = backing.keysIterator()
|
||||
|
||||
override fun removeAll(elements: Collection<E>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.removeAll(elements)
|
||||
}
|
||||
|
||||
override fun retainAll(elements: Collection<E>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.retainAll(elements)
|
||||
}
|
||||
}
|
||||
|
||||
internal class HashMapValues<V> internal constructor(
|
||||
internal class MapBuilderValues<V> internal constructor(
|
||||
val backing: MapBuilder<*, V>
|
||||
) : MutableCollection<V>, AbstractMutableCollection<V>() {
|
||||
|
||||
@@ -575,9 +583,19 @@ internal class HashMapValues<V> internal constructor(
|
||||
override fun clear() = backing.clear()
|
||||
override fun iterator(): MutableIterator<V> = backing.valuesIterator()
|
||||
override fun remove(element: V): Boolean = backing.removeValue(element)
|
||||
|
||||
override fun removeAll(elements: Collection<V>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.removeAll(elements)
|
||||
}
|
||||
|
||||
override fun retainAll(elements: Collection<V>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.retainAll(elements)
|
||||
}
|
||||
}
|
||||
|
||||
internal class HashMapEntrySet<K, V> internal constructor(
|
||||
internal class MapBuilderEntries<K, V> internal constructor(
|
||||
val backing: MapBuilder<K, V>
|
||||
) : MutableSet<MutableMap.MutableEntry<K, V>>, AbstractMutableSet<MutableMap.MutableEntry<K, V>>() {
|
||||
|
||||
@@ -585,9 +603,19 @@ internal class HashMapEntrySet<K, V> internal constructor(
|
||||
override fun isEmpty(): Boolean = backing.isEmpty()
|
||||
override fun contains(element: MutableMap.MutableEntry<K, V>): Boolean = backing.containsEntry(element)
|
||||
override fun clear() = backing.clear()
|
||||
override fun add(element: MutableMap.MutableEntry<K, V>): Boolean = backing.putEntry(element)
|
||||
override fun add(element: MutableMap.MutableEntry<K, V>): Boolean = throw UnsupportedOperationException()
|
||||
override fun addAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean = throw UnsupportedOperationException()
|
||||
override fun remove(element: MutableMap.MutableEntry<K, V>): Boolean = backing.removeEntry(element)
|
||||
override fun iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> = backing.entriesIterator()
|
||||
override fun containsAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean = backing.containsAllEntries(elements)
|
||||
override fun addAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean = backing.putAllEntries(elements)
|
||||
|
||||
override fun removeAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.removeAll(elements)
|
||||
}
|
||||
|
||||
override fun retainAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.retainAll(elements)
|
||||
}
|
||||
}
|
||||
+15
-1
@@ -5,7 +5,6 @@
|
||||
|
||||
package kotlin.collections.builders
|
||||
|
||||
@PublishedApi
|
||||
internal class SetBuilder<E> internal constructor(
|
||||
private val backing: MapBuilder<E, *>
|
||||
) : MutableSet<E>, AbstractMutableSet<E>() {
|
||||
@@ -26,4 +25,19 @@ internal class SetBuilder<E> internal constructor(
|
||||
override fun add(element: E): Boolean = backing.addKey(element) >= 0
|
||||
override fun remove(element: E): Boolean = backing.removeKey(element) >= 0
|
||||
override fun iterator(): MutableIterator<E> = backing.keysIterator()
|
||||
|
||||
override fun addAll(elements: Collection<E>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.addAll(elements)
|
||||
}
|
||||
|
||||
override fun removeAll(elements: Collection<E>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.removeAll(elements)
|
||||
}
|
||||
|
||||
override fun retainAll(elements: Collection<E>): Boolean {
|
||||
backing.checkIsMutable()
|
||||
return super.retainAll(elements)
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ package kotlin.collections
|
||||
|
||||
import kotlin.contracts.*
|
||||
import kotlin.random.Random
|
||||
import kotlin.collections.builders.*
|
||||
|
||||
internal object EmptyIterator : ListIterator<Nothing> {
|
||||
override fun hasNext(): Boolean = false
|
||||
@@ -170,9 +169,15 @@ public inline fun <T> MutableList(size: Int, init: (index: Int) -> T): MutableLi
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <E> buildList(@BuilderInference builderAction: MutableList<E>.() -> Unit): List<E> {
|
||||
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
||||
return ListBuilder<E>().apply(builderAction).build()
|
||||
return buildListInternal(builderAction)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal expect inline fun <E> buildListInternal(builderAction: MutableList<E>.() -> Unit): List<E>
|
||||
|
||||
/**
|
||||
* Builds a new read-only [List] by populating a [MutableList] using the given [builderAction]
|
||||
* and returning a read-only list with the same elements.
|
||||
@@ -191,9 +196,14 @@ public inline fun <E> buildList(@BuilderInference builderAction: MutableList<E>.
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <E> buildList(capacity: Int, @BuilderInference builderAction: MutableList<E>.() -> Unit): List<E> {
|
||||
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
||||
return ListBuilder<E>(capacity).apply(builderAction).build()
|
||||
return buildListInternal(capacity, builderAction)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal expect inline fun <E> buildListInternal(capacity: Int, builderAction: MutableList<E>.() -> Unit): List<E>
|
||||
|
||||
/**
|
||||
* Returns an [IntRange] of the valid indices for this collection.
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
import kotlin.collections.builders.MapBuilder
|
||||
import kotlin.contracts.*
|
||||
|
||||
private object EmptyMap : Map<Any?, Nothing>, Serializable {
|
||||
@@ -140,9 +139,15 @@ public fun <K, V> linkedMapOf(vararg pairs: Pair<K, V>): LinkedHashMap<K, V> = p
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <K, V> buildMap(@BuilderInference builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> {
|
||||
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
||||
return MapBuilder<K, V>().apply(builderAction).build()
|
||||
return buildMapInternal(builderAction)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal expect inline fun <K, V> buildMapInternal(builderAction: MutableMap<K, V>.() -> Unit): Map<K, V>
|
||||
|
||||
/**
|
||||
* Builds a new read-only [Map] by populating a [MutableMap] using the given [builderAction]
|
||||
* and returning a read-only map with the same key-value pairs.
|
||||
@@ -163,23 +168,21 @@ public inline fun <K, V> buildMap(@BuilderInference builderAction: MutableMap<K,
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <K, V> buildMap(capacity: Int, @BuilderInference builderAction: MutableMap<K, V>.() -> Unit): Map<K, V> {
|
||||
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
||||
return MapBuilder<K, V>(capacity).apply(builderAction).build()
|
||||
return buildMapInternal(capacity, builderAction)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal expect inline fun <K, V> buildMapInternal(capacity: Int, builderAction: MutableMap<K, V>.() -> Unit): Map<K, V>
|
||||
|
||||
/**
|
||||
* Calculate the initial capacity of a map.
|
||||
*/
|
||||
@PublishedApi
|
||||
internal expect fun mapCapacity(expectedSize: Int): Int
|
||||
|
||||
/**
|
||||
* Checks a collection builder function capacity argument.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@PublishedApi
|
||||
internal expect fun checkBuilderCapacity(capacity: Int)
|
||||
|
||||
/**
|
||||
* Returns `true` if this map is not empty.
|
||||
* @sample samples.collections.Maps.Usage.mapIsNotEmpty
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
package kotlin.collections
|
||||
|
||||
import kotlin.contracts.*
|
||||
import kotlin.collections.builders.*
|
||||
|
||||
internal object EmptySet : Set<Nothing>, Serializable {
|
||||
private const val serialVersionUID: Long = 3406603774387020532
|
||||
@@ -126,9 +125,15 @@ public fun <T : Any> setOfNotNull(vararg elements: T?): Set<T> {
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <E> buildSet(@BuilderInference builderAction: MutableSet<E>.() -> Unit): Set<E> {
|
||||
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
||||
return SetBuilder<E>().apply(builderAction).build()
|
||||
return buildSetInternal(builderAction)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal expect inline fun <E> buildSetInternal(builderAction: MutableSet<E>.() -> Unit): Set<E>
|
||||
|
||||
/**
|
||||
* Builds a new read-only [Set] by populating a [MutableSet] using the given [builderAction]
|
||||
* and returning a read-only set with the same elements.
|
||||
@@ -149,9 +154,15 @@ public inline fun <E> buildSet(@BuilderInference builderAction: MutableSet<E>.()
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <E> buildSet(capacity: Int, @BuilderInference builderAction: MutableSet<E>.() -> Unit): Set<E> {
|
||||
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
|
||||
return SetBuilder<E>(capacity).apply(builderAction).build()
|
||||
return buildSetInternal(capacity, builderAction)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
@kotlin.internal.InlineOnly
|
||||
internal expect inline fun <E> buildSetInternal(capacity: Int, builderAction: MutableSet<E>.() -> Unit): Set<E>
|
||||
|
||||
|
||||
/** Returns this Set if it's not `null` and the empty set otherwise. */
|
||||
@kotlin.internal.InlineOnly
|
||||
|
||||
@@ -6,35 +6,55 @@ import test.collections.behaviors.setBehavior
|
||||
import kotlin.test.*
|
||||
|
||||
class ContainerBuilderTest {
|
||||
private fun <E> mutableCollectionOperations(e: E) = listOf<MutableCollection<E>.() -> Unit>(
|
||||
{ add(e) },
|
||||
{ addAll(listOf(e)) },
|
||||
{ remove(e) },
|
||||
{ removeAll(listOf(e)) },
|
||||
{ retainAll(listOf(e)) },
|
||||
{ clear() },
|
||||
{ iterator().apply { next() }.remove() }
|
||||
private fun <E> mutableCollectionOperations(present: E, absent: E) = listOf<Pair<String, MutableCollection<E>.() -> Unit>>(
|
||||
"add(present)" to { add(present) },
|
||||
"add(absent)" to { add(absent) },
|
||||
|
||||
"addAll(listOf(present))" to { addAll(listOf(present)) },
|
||||
"addAll(listOf(absent))" to { addAll(listOf(absent)) },
|
||||
"addAll(emptyList())" to { addAll(emptyList()) },
|
||||
|
||||
"remove(present)" to { remove(present) },
|
||||
"remove(absent)" to { remove(absent) },
|
||||
|
||||
"removeAll(listOf(present))" to { removeAll(listOf(present)) },
|
||||
"removeAll(emptyList())" to { removeAll(emptyList()) },
|
||||
"removeAll(this.toList())" to { removeAll(this.toList()) },
|
||||
|
||||
"retainAll(listOf(present))" to { retainAll(listOf(present)) },
|
||||
"retainAll(emptyList())" to { retainAll(emptyList()) },
|
||||
"retainAll(this.toList())" to { retainAll(this.toList()) },
|
||||
|
||||
"clear()" to { clear() },
|
||||
|
||||
"iterator().apply { next() }.remove()" to { iterator().apply { next() }.remove() }
|
||||
)
|
||||
|
||||
private fun <E> mutableListOperations(e: E) = mutableCollectionOperations(e) + listOf<MutableList<E>.() -> Unit>(
|
||||
{ add(0, e) },
|
||||
{ addAll(0, listOf(e)) },
|
||||
{ removeAt(0) },
|
||||
{ set(0, e) },
|
||||
{ listIterator().apply { next() }.remove() },
|
||||
{ listIterator(0).apply { next() }.remove() },
|
||||
{ listIterator().add(e) }
|
||||
private fun <E> mutableListOperations(present: E, absent: E) = mutableCollectionOperations(present, absent) + listOf<Pair<String, MutableList<E>.() -> Unit>>(
|
||||
"add(0, present)" to { add(0, present) },
|
||||
"addAll(0, listOf(present))" to { addAll(0, listOf(present)) },
|
||||
"addAll(0, emptyList())" to { addAll(0, emptyList()) },
|
||||
"removeAt(0)" to { removeAt(0) },
|
||||
"set(0, present)" to { set(0, present) },
|
||||
"listIterator().apply { next() }.remove()" to { listIterator().apply { next() }.remove() },
|
||||
"listIterator(0).apply { next() }.remove()" to { listIterator(0).apply { next() }.remove() },
|
||||
"listIterator().apply { next() }.set(present)" to { listIterator().apply { next() }.set(present) },
|
||||
"listIterator().add(present)" to { listIterator().add(present) }
|
||||
)
|
||||
|
||||
private fun <E> mutableSetOperations(e: E): List<MutableSet<E>.() -> Unit> = mutableCollectionOperations(e)
|
||||
private fun <E> mutableSetOperations(present: E, absent: E) = mutableCollectionOperations(present, absent) + listOf<Pair<String, MutableSet<E>.() -> Unit>>(
|
||||
// check java.util.AbstractSet.removeAll optimisation
|
||||
"removeAll(List(this.size) { absent })" to { removeAll(List(this.size) { absent }) }
|
||||
)
|
||||
|
||||
private fun <K, V> mutableMapOperations(k: K, v: V) = listOf<MutableMap<K, V>.() -> Unit>(
|
||||
{ put(k, v) },
|
||||
{ remove(k) },
|
||||
{ putAll(mapOf(k to v)) },
|
||||
{ clear() },
|
||||
{ entries.first().setValue(v) },
|
||||
{ entries.iterator().next().setValue(v) }
|
||||
private fun <K, V> mutableMapOperations(k: K, v: V) = listOf<Pair<String, MutableMap<K, V>.() -> Unit>>(
|
||||
"put(k, v)" to { put(k, v) },
|
||||
"remove(k)" to { remove(k) },
|
||||
"putAll(mapOf(k to v))" to { putAll(mapOf(k to v)) },
|
||||
"putAll(emptyMap())" to { putAll(emptyMap()) },
|
||||
"clear()" to { clear() },
|
||||
"entries.first().setValue(v)" to { entries.first().setValue(v) },
|
||||
"entries.iterator().next().setValue(v)" to { entries.iterator().next().setValue(v) }
|
||||
)
|
||||
|
||||
@Test
|
||||
@@ -44,10 +64,14 @@ class ContainerBuilderTest {
|
||||
add('c')
|
||||
}
|
||||
|
||||
val y = buildList(4) {
|
||||
val subList: MutableList<Char>
|
||||
|
||||
val y = buildList<Char>(4) {
|
||||
add('a')
|
||||
addAll(x)
|
||||
add('d')
|
||||
|
||||
subList = subList(0, 4)
|
||||
}
|
||||
|
||||
compare(listOf('a', 'b', 'c', 'd'), y) { listBehavior() }
|
||||
@@ -60,9 +84,10 @@ class ContainerBuilderTest {
|
||||
}
|
||||
|
||||
assertTrue(y is MutableList<Char>)
|
||||
for (operation in mutableListOperations('a')) {
|
||||
assertFailsWith<UnsupportedOperationException> { y.operation() }
|
||||
assertFailsWith<UnsupportedOperationException> { y.subList(1, 3).operation() }
|
||||
for ((fName, operation) in mutableListOperations('b', 'x')) {
|
||||
assertFailsWith<UnsupportedOperationException>("y.$fName") { y.operation() }
|
||||
assertFailsWith<UnsupportedOperationException>("y.subList(1, 3).$fName") { y.subList(1, 3).operation() }
|
||||
assertFailsWith<UnsupportedOperationException>("subList.$fName") { subList.operation() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,10 +115,12 @@ class ContainerBuilderTest {
|
||||
val subSubList = subList.subList(2, 4)
|
||||
// buffer reallocation should happen
|
||||
repeat(20) { subSubList.add('x') }
|
||||
repeat(20) { subSubList.add(subSubList.size - 2 * it, 'y') }
|
||||
|
||||
compare("ab123${"x".repeat(20)}e".toList(), this) { listBehavior() }
|
||||
compare("b123${"x".repeat(20)}".toList(), subList) { listBehavior() }
|
||||
compare("23${"x".repeat(20)}".toList(), subSubList) { listBehavior() }
|
||||
val addedChars = "xy".repeat(20)
|
||||
compare("ab123${addedChars}e".toList(), this) { listBehavior() }
|
||||
compare("b123$addedChars".toList(), subList) { listBehavior() }
|
||||
compare("23$addedChars".toList(), subSubList) { listBehavior() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,8 +145,8 @@ class ContainerBuilderTest {
|
||||
}
|
||||
|
||||
assertTrue(y is MutableSet<Char>)
|
||||
for (operation in mutableSetOperations('b')) {
|
||||
assertFailsWith<UnsupportedOperationException> { y.operation() }
|
||||
for ((fName, operation) in mutableSetOperations('b', 'x')) {
|
||||
assertFailsWith<UnsupportedOperationException>("y.$fName") { y.operation() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,17 +172,23 @@ class ContainerBuilderTest {
|
||||
}
|
||||
|
||||
assertTrue(y is MutableMap<Char, Int>)
|
||||
for (operation in mutableMapOperations('a', 0)) {
|
||||
assertFailsWith<UnsupportedOperationException> { y.operation() }
|
||||
for ((fName, operation) in mutableMapOperations('a', 1) + mutableMapOperations('x', 10)) {
|
||||
assertFailsWith<UnsupportedOperationException>("y.$fName") { y.operation() }
|
||||
}
|
||||
for (operation in mutableSetOperations('a')) {
|
||||
assertFailsWith<UnsupportedOperationException> { y.keys.operation() }
|
||||
for ((fName, operation) in mutableSetOperations('a', 'x')) {
|
||||
assertFailsWith<UnsupportedOperationException>("y.keys.$fName") { y.keys.operation() }
|
||||
}
|
||||
for (operation in mutableCollectionOperations(1)) {
|
||||
assertFailsWith<UnsupportedOperationException> { y.values.operation() }
|
||||
for ((fName, operation) in mutableCollectionOperations(1, 10)) {
|
||||
assertFailsWith<UnsupportedOperationException>("y.values.$fName") { y.values.operation() }
|
||||
}
|
||||
for (operation in mutableSetOperations(y.entries.first())) {
|
||||
assertFailsWith<UnsupportedOperationException> { y.entries.operation() }
|
||||
val presentEntry = y.entries.first()
|
||||
val absentEntry: MutableMap.MutableEntry<Char, Int> = object : MutableMap.MutableEntry<Char, Int> {
|
||||
override val key: Char get() = 'x'
|
||||
override val value: Int get() = 10
|
||||
override fun setValue(newValue: Int): Int = fail("Unreachable")
|
||||
}
|
||||
for ((fName, operation) in mutableSetOperations(presentEntry, absentEntry)) {
|
||||
assertFailsWith<UnsupportedOperationException>("y.entries.$fName") { y.entries.operation() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user