package blitz.collections import kotlin.system.measureTimeMillis @Suppress("UNCHECKED_CAST") class RefVec(private val initCap: Int = 0): Vec { override var size = 0 private var cap = initCap private var array: Array? = if (initCap > 0) arrayOfNulls(initCap) else null override fun clear() { size = 0 if (array == null) return if (array!!.size <= initCap) { cap = array!!.size } else { cap = 0 array = null } } fun copyAsArray(): Array = array?.copyOfRange(0, size) ?: emptyArray() fun copyIntoArray(arr: Array, destOff: Int = 0, startOff: Int = 0) = array?.copyInto(arr, destOff, startOff, size) override fun copy(): RefVec = RefVec(size).also { it.array?.let { copyIntoArray(it) } } override fun reserve(amount: Int) { if (amount > 0 && cap - size >= amount) return if (array == null) { cap = size + amount array = arrayOfNulls(cap) } else { array = array!!.copyOf(size + amount) cap = size + amount } } override fun reserve(need: Int, totalIfRealloc: Int) { if (need > 0 && cap - size >= need) return if (array == null) { cap = size + totalIfRealloc array = arrayOfNulls(cap) } else { array = array!!.copyOf(size + totalIfRealloc) cap = size + totalIfRealloc } } override fun popBack(): T = array!![size - 1].also { reserve(-1) size -- } as T override fun get(index: Int): T = array!![index] as T override fun flip() { array = array?.reversedArray() } override fun pushBack(elem: T) { reserve(1, 8) array!![size] = elem size ++ } override fun iterator(): Iterator = object : Iterator { var index = 0 override fun hasNext(): Boolean = index < size override fun next(): T { if (!hasNext()) throw NoSuchElementException() return array!![index++] as T } } override fun toString(): String = joinToString(prefix = "[", postfix = "]") { it.toString() } override fun set(index: Int, value: T) { array!![index] = value } companion object { fun from(data: Array) = RefVec(data.size).also { it.array?.let { data.copyInto(it) } it.size += data.size } fun from(data: Iterable) = RefVec().also { bv -> data.forEach(bv::pushBack) } fun of(vararg elements: T): RefVec = RefVec(elements.size).also { it.array?.let { elements.copyInto(it) } } } }