150 lines
3.8 KiB
Kotlin
150 lines
3.8 KiB
Kotlin
package blitz.collections
|
|
|
|
import kotlin.contracts.ExperimentalContracts
|
|
import kotlin.contracts.contract
|
|
|
|
class ShortVec(private val initCap: Int = 0): Vec<Short>, BatchSequence<Short> {
|
|
override var size = 0
|
|
private var cap = initCap
|
|
private var array = ShortArray(initCap)
|
|
|
|
override fun clear() {
|
|
size = 0
|
|
if (array.size <= initCap) {
|
|
cap = array.size
|
|
} else {
|
|
cap = initCap
|
|
array = ShortArray(initCap)
|
|
}
|
|
}
|
|
|
|
fun copyAsArray(): ShortArray =
|
|
array.copyOfRange(0, size)
|
|
|
|
fun copyIntoArray(arr: ShortArray, destOff: Int = 0, startOff: Int = 0) =
|
|
array.copyInto(arr, destOff, startOff, size)
|
|
|
|
override fun copy(): ShortVec =
|
|
ShortVec(size).also {
|
|
copyIntoArray(it.array)
|
|
}
|
|
|
|
override fun reserve(amount: Int) {
|
|
if (amount > 0 && cap - size >= amount)
|
|
return
|
|
array = array.copyOf(size + amount)
|
|
cap = size + amount
|
|
}
|
|
|
|
override fun reserve(need: Int, wantIfRealloc: Int) {
|
|
if (need > 0 && cap - size >= need)
|
|
return
|
|
cap = size + wantIfRealloc
|
|
array = array.copyOf(cap)
|
|
}
|
|
|
|
override fun popBack(): Short =
|
|
array[size - 1].also {
|
|
reserve(-1)
|
|
size --
|
|
}
|
|
|
|
fun tryPopPack(dest: ShortArray, destOff: Int = 0): Int {
|
|
val can = kotlin.math.min(size, dest.size - destOff)
|
|
copyIntoArray(dest, destOff, size - can)
|
|
reserve(-can)
|
|
size -= can
|
|
return can
|
|
}
|
|
|
|
fun popBack(dest: ShortArray, destOff: Int = 0) {
|
|
val destCopySize = dest.size - destOff
|
|
require(size >= destCopySize)
|
|
copyIntoArray(dest, destOff, size - destCopySize)
|
|
reserve(-destCopySize)
|
|
size -= destCopySize
|
|
}
|
|
|
|
@OptIn(ExperimentalContracts::class)
|
|
inline fun consumePopBack(batching: ShortArray, fn: (ShortArray, Int) -> Unit) {
|
|
contract {
|
|
callsInPlace(fn)
|
|
}
|
|
|
|
while (true) {
|
|
val rem = tryPopPack(batching)
|
|
if (rem == 0) break
|
|
|
|
fn(batching, rem)
|
|
}
|
|
}
|
|
|
|
inline fun consumePopBack(batching: ShortArray, fn: (Short) -> Unit) =
|
|
consumePopBack(batching) { batch, count ->
|
|
repeat(count) {
|
|
fn(batch[it])
|
|
}
|
|
}
|
|
|
|
@OptIn(ExperimentalContracts::class)
|
|
inline fun consumePopBackSlicedBatches(batching: ShortArray, fn: (ShortArray) -> Unit) {
|
|
contract {
|
|
callsInPlace(fn)
|
|
}
|
|
|
|
while (true) {
|
|
val rem = tryPopPack(batching)
|
|
if (rem == 0) break
|
|
|
|
if (rem == batching.size)
|
|
fn(batching)
|
|
else
|
|
fn(batching.copyOf(rem))
|
|
}
|
|
}
|
|
|
|
override fun get(index: Int): Short =
|
|
array[index]
|
|
|
|
override fun flip() {
|
|
array = array.reversedArray()
|
|
}
|
|
|
|
fun pushBack(arr: ShortArray) {
|
|
reserve(arr.size)
|
|
arr.copyInto(array, size)
|
|
size += arr.size
|
|
}
|
|
|
|
override fun pushBack(elem: Short) {
|
|
reserve(1, 8)
|
|
array[size] = elem
|
|
size ++
|
|
}
|
|
|
|
override fun iterator(): BatchIterator<Short> =
|
|
array.asSequence().asBatch().iterator()
|
|
|
|
override fun toString(): String =
|
|
contents.toString()
|
|
|
|
override fun set(index: Int, value: Short) {
|
|
array[index] = value
|
|
}
|
|
|
|
override fun indexOf(value: Short): Int =
|
|
array.indexOf(value)
|
|
|
|
companion object {
|
|
fun from(bytes: ShortArray) =
|
|
ShortVec(bytes.size).also {
|
|
bytes.copyInto(it.array)
|
|
it.size += bytes.size
|
|
}
|
|
|
|
fun from(bytes: Sequence<Short>) =
|
|
ShortVec().also { bv ->
|
|
bytes.forEach(bv::pushBack)
|
|
}
|
|
}
|
|
} |