commonMain.implementations.immutableList.SmallPersistentVector.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlinx-collections-immutable-jvm Show documentation
Show all versions of kotlinx-collections-immutable-jvm Show documentation
Kotlin Immutable Collections multiplatform library
/*
* Copyright 2016-2019 JetBrains s.r.o.
* Use of this source code is governed by the Apache 2.0 License that can be found in the LICENSE.txt file.
*/
package kotlinx.collections.immutable.implementations.immutableList
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.internal.ListImplementation.checkElementIndex
import kotlinx.collections.immutable.internal.ListImplementation.checkPositionIndex
import kotlinx.collections.immutable.internal.assert
import kotlinx.collections.immutable.mutate
internal class SmallPersistentVector(private val buffer: Array) : ImmutableList, AbstractPersistentList() {
init {
assert(buffer.size <= MAX_BUFFER_SIZE)
}
override val size: Int
get() = buffer.size
private fun bufferOfSize(size: Int): Array {
return arrayOfNulls(size)
}
override fun add(element: E): PersistentList {
if (size < MAX_BUFFER_SIZE) {
val newBuffer = buffer.copyOf(size + 1)
newBuffer[size] = element
return SmallPersistentVector(newBuffer)
}
val tail = presizedBufferWith(element)
return PersistentVector(buffer, tail, size + 1, 0)
}
override fun addAll(elements: Collection): PersistentList {
if (size + elements.size <= MAX_BUFFER_SIZE) {
val newBuffer = buffer.copyOf(size + elements.size)
// TODO: investigate performance of elements.toArray + copyInto
var index = size
for (element in elements) {
newBuffer[index++] = element
}
return SmallPersistentVector(newBuffer)
}
return mutate { it.addAll(elements) }
}
override fun removeAll(predicate: (E) -> Boolean): PersistentList {
var newBuffer = buffer
var newSize = size
var anyRemoved = false
for (index in 0 until size) {
@Suppress("UNCHECKED_CAST")
val element = buffer[index] as E
if (predicate(element)) {
if (!anyRemoved) {
newBuffer = buffer.copyOf()
newSize = index
anyRemoved = true
}
} else if (anyRemoved) {
newBuffer[newSize++] = element
}
}
return when (newSize) {
size -> this
0 -> EMPTY
else -> SmallPersistentVector(newBuffer.copyOfRange(0, newSize))
}
}
override fun addAll(index: Int, c: Collection): PersistentList {
checkPositionIndex(index, size)
if (size + c.size <= MAX_BUFFER_SIZE) {
val newBuffer = bufferOfSize(size + c.size)
buffer.copyInto(newBuffer, endIndex = index)
buffer.copyInto(newBuffer, index + c.size, index, size)
var position = index
for (element in c) {
newBuffer[position++] = element
}
return SmallPersistentVector(newBuffer)
}
return mutate { it.addAll(index, c) }
}
override fun add(index: Int, element: E): PersistentList {
checkPositionIndex(index, size)
if (index == size) {
return add(element)
}
if (size < MAX_BUFFER_SIZE) {
// TODO: copyOf + one copyInto?
val newBuffer = bufferOfSize(size + 1)
buffer.copyInto(newBuffer, endIndex = index)
buffer.copyInto(newBuffer, index + 1, index, size)
newBuffer[index] = element
return SmallPersistentVector(newBuffer)
}
val root = buffer.copyOf()
buffer.copyInto(root, index + 1, index, size - 1)
root[index] = element
val tail = presizedBufferWith(buffer[MAX_BUFFER_SIZE_MINUS_ONE])
return PersistentVector(root, tail, size + 1, 0)
}
override fun removeAt(index: Int): PersistentList {
checkElementIndex(index, size)
if (size == 1) {
return EMPTY
}
val newBuffer = buffer.copyOf(size - 1)
buffer.copyInto(newBuffer, index, index + 1, size)
return SmallPersistentVector(newBuffer)
}
override fun builder(): PersistentList.Builder {
return PersistentVectorBuilder(this, null, buffer, 0)
}
override fun indexOf(element: E): Int {
return buffer.indexOf(element)
}
override fun lastIndexOf(element: E): Int {
return buffer.lastIndexOf(element)
}
override fun listIterator(index: Int): ListIterator {
checkPositionIndex(index, size)
@Suppress("UNCHECKED_CAST")
return BufferIterator(buffer as Array, index, size)
}
override fun get(index: Int): E {
// TODO: use elementAt(index)?
checkElementIndex(index, size)
@Suppress("UNCHECKED_CAST")
return buffer[index] as E
}
override fun set(index: Int, element: E): PersistentList {
checkElementIndex(index, size)
val newBuffer = buffer.copyOf()
newBuffer[index] = element
return SmallPersistentVector(newBuffer)
}
companion object {
val EMPTY = SmallPersistentVector(emptyArray())
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy