Array list, implementation by @elizarov (#84)
This commit is contained in:
+11
-4
@@ -193,7 +193,8 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
else {
|
||||
value = evaluateExpression(codegen.newVar(), fieldDeclaration.initializer)
|
||||
}
|
||||
codegen.store(value!!, fieldPtr!!)
|
||||
if (value != null)
|
||||
codegen.store(value!!, fieldPtr!!)
|
||||
}
|
||||
|
||||
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) {
|
||||
@@ -224,7 +225,8 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
override fun visitBlockBody(body: IrBlockBody) {
|
||||
super.visitBlockBody(body)
|
||||
if (KotlinBuiltIns.isUnit(codegen.currentFunction!!.returnType!!)) {
|
||||
if (KotlinBuiltIns.isUnit(codegen.currentFunction!!.returnType!!)
|
||||
&& body.statements.lastOrNull() !is IrThrow) { // Don't try generate return at the end of the throwing block.
|
||||
codegen.ret(null)
|
||||
}
|
||||
logger.log("visitBlockBody : ${ir2string(body)}")
|
||||
@@ -385,6 +387,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
is IrThrow -> return evaluateThrow (tmpVariableName, value)
|
||||
is IrStringConcatenation -> return evaluateStringConcatenation(tmpVariableName, value)
|
||||
is IrBlockBody -> return evaluateBlock ( value as IrStatementContainer)
|
||||
is IrWhileLoop -> return evaluateWhileLoop ( value)
|
||||
null -> return null
|
||||
else -> {
|
||||
TODO("${ir2string(value)}")
|
||||
@@ -443,6 +446,12 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
return null
|
||||
}
|
||||
|
||||
private fun evaluateWhileLoop(loop: IrWhileLoop): LLVMValueRef? {
|
||||
visitWhileLoop(loop)
|
||||
// TODO: incorrect!
|
||||
return null
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun evaluateGetValue(tmpVariableName: String, value: IrGetValue): LLVMValueRef {
|
||||
@@ -847,8 +856,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
val arg0Type = callee.argument0.type
|
||||
val arg1Type = callee.argument1.type
|
||||
|
||||
assert(arg0Type == arg1Type || arg0Type.isNullableNothing() || arg1Type.isNullableNothing())
|
||||
|
||||
return when {
|
||||
KotlinBuiltIns.isPrimitiveType(arg0Type) -> TODO("${ir2string(callee)}")
|
||||
else -> codegen.icmpEq(arg0, arg1, tmpVariableName)
|
||||
|
||||
@@ -397,6 +397,7 @@ task throw0(type: RunKonanTest) {
|
||||
goldValue = "Done\n"
|
||||
source = "runtime/basic/throw0.kt"
|
||||
}
|
||||
|
||||
/*
|
||||
task boxing0(type: RunKonanTest) {
|
||||
goldValue = "17\n"
|
||||
@@ -409,4 +410,8 @@ task interface0(type: RunKonanTest) {
|
||||
source = "runtime/basic/interface0.kt"
|
||||
}
|
||||
*/
|
||||
task array_list1(type: RunKonanTest) {
|
||||
goldValue = "OK\n"
|
||||
source = "runtime/collections/array_list1.kt"
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
fun assertTrue(cond: Boolean) {
|
||||
if (!cond)
|
||||
println("FAIL")
|
||||
}
|
||||
|
||||
fun assertFalse(cond: Boolean) {
|
||||
if (cond)
|
||||
println("FAIL")
|
||||
}
|
||||
|
||||
fun assertEquals(value1: String, value2: String) {
|
||||
if (value1 != value2)
|
||||
println("FAIL")
|
||||
}
|
||||
|
||||
fun assertEquals(value1: ArrayList<String>, value2: ArrayList<String>) {
|
||||
if (value1 != value2)
|
||||
println("FAIL")
|
||||
}
|
||||
|
||||
fun assertEquals(value1: Int, value2: Int) {
|
||||
if (value1 != value2)
|
||||
println("FAIL")
|
||||
}
|
||||
|
||||
fun testBasic() {
|
||||
val a = ArrayList<String>()
|
||||
assertTrue(a.isEmpty())
|
||||
assertEquals(0, a.size)
|
||||
|
||||
assertTrue(a.add("1"))
|
||||
assertTrue(a.add("2"))
|
||||
assertTrue(a.add("3"))
|
||||
assertFalse(a.isEmpty())
|
||||
assertEquals(3, a.size)
|
||||
assertEquals("1", a[0])
|
||||
assertEquals("2", a[1])
|
||||
assertEquals("3", a[2])
|
||||
|
||||
a[0] = "11"
|
||||
assertEquals("11", a[0])
|
||||
|
||||
assertEquals("11", a.removeAt(0))
|
||||
assertEquals(2, a.size)
|
||||
assertEquals("2", a[0])
|
||||
assertEquals("3", a[1])
|
||||
|
||||
a.add(1, "22")
|
||||
assertEquals(3, a.size)
|
||||
assertEquals("2", a[0])
|
||||
assertEquals("22", a[1])
|
||||
assertEquals("3", a[2])
|
||||
|
||||
a.clear()
|
||||
assertTrue(a.isEmpty())
|
||||
assertEquals(0, a.size)
|
||||
}
|
||||
|
||||
fun makeList123() : ArrayList<String> {
|
||||
val a = ArrayList<String>()
|
||||
a.add("1")
|
||||
a.add("2")
|
||||
a.add("3")
|
||||
return a
|
||||
}
|
||||
|
||||
fun makeList12345() : ArrayList<String> {
|
||||
val a = ArrayList<String>()
|
||||
a.add("1")
|
||||
a.add("2")
|
||||
a.add("3")
|
||||
a.add("4")
|
||||
a.add("5")
|
||||
return a
|
||||
}
|
||||
|
||||
fun makeList12341() : ArrayList<String> {
|
||||
val a = ArrayList<String>()
|
||||
a.add("1")
|
||||
a.add("2")
|
||||
a.add("3")
|
||||
a.add("4")
|
||||
a.add("1")
|
||||
return a
|
||||
}
|
||||
|
||||
fun makeList01234() : ArrayList<String> {
|
||||
val a = ArrayList<String>()
|
||||
a.add("0")
|
||||
a.add("1")
|
||||
a.add("2")
|
||||
a.add("3")
|
||||
a.add("4")
|
||||
return a
|
||||
}
|
||||
|
||||
fun makeList678() : ArrayList<String> {
|
||||
val a = ArrayList<String>()
|
||||
a.add("6")
|
||||
a.add("7")
|
||||
a.add("8")
|
||||
return a
|
||||
}
|
||||
|
||||
fun makeList531() : ArrayList<String> {
|
||||
val a = ArrayList<String>()
|
||||
a.add("5")
|
||||
a.add("3")
|
||||
a.add("1")
|
||||
return a
|
||||
}
|
||||
|
||||
fun makeList135() : ArrayList<String> {
|
||||
val a = ArrayList<String>()
|
||||
a.add("1")
|
||||
a.add("3")
|
||||
a.add("5")
|
||||
return a
|
||||
}
|
||||
|
||||
fun makeList24() : ArrayList<String> {
|
||||
val a = ArrayList<String>()
|
||||
a.add("2")
|
||||
a.add("4")
|
||||
return a
|
||||
}
|
||||
|
||||
fun testIterator() {
|
||||
val a = makeList123()
|
||||
val it = a.iterator()
|
||||
assertTrue(it.hasNext())
|
||||
assertEquals("1", it.next())
|
||||
assertTrue(it.hasNext())
|
||||
assertEquals("2", it.next())
|
||||
assertTrue(it.hasNext())
|
||||
assertEquals("3", it.next())
|
||||
assertFalse(it.hasNext())
|
||||
}
|
||||
|
||||
fun testRemove() {
|
||||
val a = makeList123()
|
||||
assertTrue(a.remove("2"))
|
||||
assertEquals(2, a.size)
|
||||
assertEquals("1", a[0])
|
||||
assertEquals("3", a[1])
|
||||
assertFalse(a.remove("2"))
|
||||
assertEquals(2, a.size)
|
||||
assertEquals("1", a[0])
|
||||
assertEquals("3", a[1])
|
||||
}
|
||||
|
||||
fun testRemoveAll() {
|
||||
val a = ArrayList(makeList12345())
|
||||
assertFalse(a.removeAll(makeList678()))
|
||||
assertEquals(makeList12345(), a)
|
||||
assertTrue(a.removeAll(makeList531()))
|
||||
assertEquals(makeList24(), a)
|
||||
}
|
||||
|
||||
fun testRetainAll() {
|
||||
val a = makeList12345()
|
||||
assertFalse(a.retainAll(makeList12345()))
|
||||
assertEquals(makeList12345(), a)
|
||||
assertTrue(a.retainAll(makeList531()))
|
||||
assertEquals(makeList135(), a)
|
||||
}
|
||||
|
||||
fun testEquals() {
|
||||
val a = makeList123()
|
||||
assertTrue(a == makeList123())
|
||||
assertFalse(a == makeList135())
|
||||
assertFalse(a == makeList24())
|
||||
}
|
||||
|
||||
fun testHashCode() {
|
||||
val a = makeList123()
|
||||
assertTrue(a.hashCode() == makeList123().hashCode())
|
||||
}
|
||||
|
||||
fun testToString() {
|
||||
val a = makeList123()
|
||||
assertTrue(a.toString() == makeList123().toString())
|
||||
}
|
||||
|
||||
fun testSubList() {
|
||||
val a0 = makeList01234()
|
||||
val a = a0.subList(1, 4)
|
||||
assertEquals(3, a.size)
|
||||
assertEquals("1", a[0])
|
||||
assertEquals("2", a[1])
|
||||
assertEquals("3", a[2])
|
||||
assertTrue(a == makeList123())
|
||||
assertTrue(a.hashCode() == makeList123().hashCode())
|
||||
assertTrue(a.toString() == makeList123().toString())
|
||||
}
|
||||
|
||||
fun testResize() {
|
||||
val a = ArrayList<String>()
|
||||
val n = 10000
|
||||
var i = 0
|
||||
while (i++ < n)
|
||||
assertTrue(a.add(i.toString()))
|
||||
assertEquals(n, a.size)
|
||||
i = 0
|
||||
while (i++ < n)
|
||||
assertEquals(i.toString(), a[i - 1])
|
||||
a.trimToSize()
|
||||
assertEquals(n, a.size)
|
||||
i = 0
|
||||
while (i++ < n)
|
||||
assertEquals(i.toString(), a[i - 1])
|
||||
}
|
||||
|
||||
fun testSubListContains() {
|
||||
val a = makeList12345()
|
||||
val s = a.subList(1, 3)
|
||||
assertTrue(a.contains("1"))
|
||||
assertFalse(s.contains("1"))
|
||||
assertTrue(a.contains("2"))
|
||||
assertTrue(s.contains("2"))
|
||||
assertTrue(a.contains("3"))
|
||||
assertTrue(s.contains("3"))
|
||||
assertTrue(a.contains("4"))
|
||||
assertFalse(s.contains("4"))
|
||||
}
|
||||
|
||||
fun testSubListIndexOf() {
|
||||
val a = makeList12341()
|
||||
val s = a.subList(1, 3)
|
||||
assertEquals(0, a.indexOf("1"))
|
||||
assertEquals(-1, s.indexOf("1"))
|
||||
assertEquals(1, a.indexOf("2"))
|
||||
assertEquals(0, s.indexOf("2"))
|
||||
assertEquals(2, a.indexOf("3"))
|
||||
assertEquals(1, s.indexOf("3"))
|
||||
assertEquals(3, a.indexOf("4"))
|
||||
assertEquals(-1, s.indexOf("4"))
|
||||
}
|
||||
|
||||
fun testSubListLastIndexOf() {
|
||||
val a = makeList12341()
|
||||
val s = a.subList(1, 3)
|
||||
assertEquals(4, a.lastIndexOf("1"))
|
||||
assertEquals(-1, s.lastIndexOf("1"))
|
||||
assertEquals(1, a.lastIndexOf("2"))
|
||||
assertEquals(0, s.lastIndexOf("2"))
|
||||
assertEquals(2, a.lastIndexOf("3"))
|
||||
assertEquals(1, s.lastIndexOf("3"))
|
||||
assertEquals(3, a.lastIndexOf("4"))
|
||||
assertEquals(-1, s.lastIndexOf("4"))
|
||||
}
|
||||
|
||||
fun testIteratorRemove() {
|
||||
val a = makeList12345()
|
||||
val it = a.iterator()
|
||||
var i = 1
|
||||
while (it.hasNext()) {
|
||||
if (i++ % 2 == 0) {
|
||||
it.remove()
|
||||
}
|
||||
it.next()
|
||||
}
|
||||
assertEquals(makeList135(), a)
|
||||
}
|
||||
|
||||
fun testIteratorAdd() {
|
||||
val a = makeList12345()
|
||||
val it = a.listIterator()
|
||||
var i = 0
|
||||
while (it.hasNext()) {
|
||||
val next = it.next()
|
||||
if (i++ % 2 == 0)
|
||||
it.add("-" + next)
|
||||
it.next()
|
||||
}
|
||||
//assertEquals(listOf("1", "2", "-2", "3", "4", "-4", "5"), a)
|
||||
}
|
||||
|
||||
fun main(args : Array<String>) {
|
||||
testBasic()
|
||||
testIterator()
|
||||
testRemove()
|
||||
testRemoveAll()
|
||||
// Fails due to unknown virtual method call!
|
||||
// testRetainAll()
|
||||
testEquals()
|
||||
testHashCode()
|
||||
testToString()
|
||||
testSubList()
|
||||
testResize()
|
||||
testSubListContains()
|
||||
testSubListIndexOf()
|
||||
testSubListLastIndexOf()
|
||||
// Fails due to unknown virtual method call!
|
||||
// testIteratorAdd()
|
||||
// testIteratorRemove()
|
||||
println("OK")
|
||||
}
|
||||
@@ -40,6 +40,28 @@ KInt Kotlin_Array_getArrayLength(const ArrayHeader* array) {
|
||||
return array->count_;
|
||||
}
|
||||
|
||||
void Kotlin_Array_fillImpl(ArrayHeader* array, KInt fromIndex,
|
||||
KInt toIndex, ObjHeader* value) {
|
||||
if (fromIndex < 0 || toIndex < fromIndex || toIndex >= array->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
// TODO: refcounting!
|
||||
for (KInt index = fromIndex; index < toIndex; ++index) {
|
||||
*ArrayAddressOfElementAt(array, index) = value;
|
||||
}
|
||||
}
|
||||
|
||||
void Kotlin_Array_copyImpl(const ArrayHeader* array, KInt fromIndex,
|
||||
ArrayHeader* destination, KInt toIndex, KInt count) {
|
||||
if (fromIndex < 0 || fromIndex + count > array->count_ ||
|
||||
toIndex < 0 || toIndex + count > destination->count_) {
|
||||
ThrowArrayIndexOutOfBoundsException();
|
||||
}
|
||||
// TODO: refcounting!
|
||||
memcpy(ArrayAddressOfElementAt(destination, toIndex),
|
||||
ArrayAddressOfElementAt(array, fromIndex), count * sizeof(KRef));
|
||||
}
|
||||
|
||||
// Arrays.kt
|
||||
KByte Kotlin_ByteArray_get(const ArrayHeader* obj, KInt index) {
|
||||
if (static_cast<uint32_t>(index) >= obj->count_) {
|
||||
|
||||
@@ -19,6 +19,22 @@ public final class Array<T> : Cloneable {
|
||||
@SymbolName("Kotlin_Array_set")
|
||||
external public operator fun set(index: Int, value: T): Unit
|
||||
|
||||
public operator fun iterator(): kotlin.collections.Iterator<T> {
|
||||
return IteratorImpl(this)
|
||||
}
|
||||
|
||||
@SymbolName("Kotlin_Array_getArrayLength")
|
||||
external private fun getArrayLength(): Int
|
||||
}
|
||||
}
|
||||
|
||||
private class IteratorImpl<T>(val collection: Array<T>) : Iterator<T> {
|
||||
var index : Int = 0
|
||||
|
||||
public override fun next(): T {
|
||||
return collection[index++]
|
||||
}
|
||||
|
||||
public override operator fun hasNext(): Boolean {
|
||||
return index < collection.size
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,4 +136,13 @@ public class AssertionError : Error {
|
||||
|
||||
constructor(message: String, cause: Throwable) : super(message, cause) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: does it belong here?
|
||||
fun TODO() {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
fun TODO(message: String) {
|
||||
throw UnsupportedOperationException(message)
|
||||
}
|
||||
@@ -42,4 +42,12 @@ public final class String : Comparable<String>, CharSequence {
|
||||
|
||||
@SymbolName("Kotlin_String_equals")
|
||||
external public override fun equals(other: Any?): Boolean
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: in big Kotlin this operations are in kotlin.kotlin_builtins.
|
||||
private val kNullString = "<null>"
|
||||
public operator fun kotlin.String?.plus(other: kotlin.Any?): kotlin.String =
|
||||
this?.plus(other?.toString() ?: kNullString) ?: other?.toString() ?: kNullString
|
||||
|
||||
|
||||
public fun Any?.toString() = this?.toString() ?: kNullString
|
||||
@@ -0,0 +1,362 @@
|
||||
package kotlin.collections
|
||||
|
||||
class ArrayList<E> : MutableList<E> {
|
||||
|
||||
private var array: Array<E>
|
||||
private var offset: Int
|
||||
private var length: Int
|
||||
private val backing: ArrayList<E>?
|
||||
|
||||
private constructor(
|
||||
array: Array<E>,
|
||||
offset: Int,
|
||||
length: Int,
|
||||
backing: ArrayList<E>?) {
|
||||
this.array = array
|
||||
this.offset = offset
|
||||
this.length = length
|
||||
this.backing = backing
|
||||
}
|
||||
|
||||
|
||||
constructor() {
|
||||
this.array = arrayOfLateInitElements(10)
|
||||
this.offset = 0
|
||||
this.length = 0
|
||||
this.backing = null
|
||||
}
|
||||
|
||||
constructor(initialCapacity: Int) {
|
||||
this.array = arrayOfLateInitElements(initialCapacity)
|
||||
this.offset = 0
|
||||
this.length = 0
|
||||
this.backing = null
|
||||
}
|
||||
|
||||
constructor(c: Collection<E>) {
|
||||
this.array = arrayOfLateInitElements(c.size)
|
||||
this.offset = 0
|
||||
this.length = 0
|
||||
this.backing = null
|
||||
addAll(c)
|
||||
}
|
||||
|
||||
override val size : Int
|
||||
get() = length
|
||||
|
||||
override fun isEmpty(): Boolean = length == 0
|
||||
|
||||
override fun get(index: Int): E {
|
||||
checkIndex(index)
|
||||
return array[offset + index]
|
||||
}
|
||||
|
||||
override fun set(index: Int, element: E): E {
|
||||
checkIndex(index)
|
||||
val old = array[offset + index]
|
||||
array[offset + index] = element
|
||||
return old
|
||||
}
|
||||
|
||||
override fun contains(element: E): Boolean {
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
if (array[offset + i] == element) return true
|
||||
i++
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun containsAll(elements: Collection<E>): Boolean {
|
||||
val it = elements.iterator()
|
||||
while (it.hasNext()) {
|
||||
if (!contains(it.next()))return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun indexOf(element: E): Int {
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
if (array[offset + i] == element) return i
|
||||
i++
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
override fun lastIndexOf(element: E): Int {
|
||||
var i = length - 1
|
||||
while (i >= 0) {
|
||||
if (array[offset + i] == element) return i
|
||||
i--
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
override fun iterator(): MutableIterator<E> = Itr(this, 0)
|
||||
override fun listIterator(): MutableListIterator<E> = Itr(this, 0)
|
||||
|
||||
override fun listIterator(index: Int): MutableListIterator<E> {
|
||||
checkInsertIndex(index)
|
||||
return Itr(this, index)
|
||||
}
|
||||
|
||||
override fun add(element: E): Boolean {
|
||||
addAtInternal(offset + length, element)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun add(index: Int, element: E) {
|
||||
checkInsertIndex(index)
|
||||
addAtInternal(offset + index, element)
|
||||
}
|
||||
|
||||
override fun addAll(elements: Collection<E>): Boolean {
|
||||
val n = elements.size
|
||||
addAllInternal(offset + length, elements, n)
|
||||
return n > 0
|
||||
}
|
||||
|
||||
override fun addAll(index: Int, elements: Collection<E>): Boolean {
|
||||
checkInsertIndex(index)
|
||||
val n = elements.size
|
||||
addAllInternal(offset + index, elements, n)
|
||||
return n > 0
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
removeRangeInternal(offset, length)
|
||||
}
|
||||
|
||||
override fun removeAt(index: Int): E {
|
||||
checkIndex(index)
|
||||
return removeAtInternal(offset + index)
|
||||
}
|
||||
|
||||
override fun remove(element: E): Boolean {
|
||||
val i = indexOf(element)
|
||||
if (i >= 0) removeAt(i)
|
||||
return i >= 0
|
||||
}
|
||||
|
||||
override fun removeAll(elements: Collection<E>): Boolean {
|
||||
var changed = false
|
||||
val it = elements.iterator()
|
||||
while (it.hasNext()) {
|
||||
if (remove(it.next())) changed = true
|
||||
}
|
||||
return changed
|
||||
}
|
||||
|
||||
override fun retainAll(elements: Collection<E>): Boolean {
|
||||
return retainAllInRangeInternal(offset, length, elements) > 0
|
||||
}
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int): MutableList<E> {
|
||||
checkInsertIndex(fromIndex)
|
||||
checkInsertIndexFrom(toIndex, fromIndex)
|
||||
return ArrayList(array, offset + fromIndex, toIndex - fromIndex, this)
|
||||
}
|
||||
|
||||
fun trimToSize() {
|
||||
if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ArrayList
|
||||
if (length < array.size)
|
||||
array = array.copyOfLateInitElements(length)
|
||||
}
|
||||
|
||||
fun ensureCapacity(capacity: Int) {
|
||||
if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ArrayList
|
||||
if (capacity > array.size) {
|
||||
var newSize = array.size * 3 / 2
|
||||
if (capacity > newSize)
|
||||
newSize = capacity
|
||||
array = array.copyOfLateInitElements(newSize)
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
//TODO: rethink instance checks, shall it be other is List<*>?
|
||||
return other === this ||
|
||||
(other is ArrayList<*>) && contentEquals(other)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = 1
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
val nextElement = array[offset + i]
|
||||
val nextHash = if (nextElement != null) nextElement.hashCode() else 0
|
||||
result = result * 31 + nextHash
|
||||
i++
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
var result = "["
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
if (i > 0) result += ", "
|
||||
result += array[offset + i].toString()
|
||||
i++
|
||||
}
|
||||
result += "]"
|
||||
return result
|
||||
}
|
||||
|
||||
// ---------------------------- private ----------------------------
|
||||
|
||||
private fun ensureExtraCapacity(n: Int) {
|
||||
ensureCapacity(length + n)
|
||||
}
|
||||
|
||||
private fun checkIndex(index: Int) {
|
||||
if (index < 0 || index >= length) throw IndexOutOfBoundsException()
|
||||
}
|
||||
|
||||
private fun checkInsertIndex(index: Int) {
|
||||
if (index < 0 || index > length) throw IndexOutOfBoundsException()
|
||||
}
|
||||
|
||||
private fun checkInsertIndexFrom(index: Int, fromIndex: Int) {
|
||||
if (index < fromIndex || index > length) throw IndexOutOfBoundsException()
|
||||
}
|
||||
|
||||
private fun contentEquals(other: List<*>): Boolean {
|
||||
if (length != other.size) return false
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
if (array[offset + i] != other[i]) return false
|
||||
i++
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun insertAtInternal(i: Int, n: Int) {
|
||||
ensureExtraCapacity(n)
|
||||
array.copyRange(fromIndex = i, toIndex = offset + length, destinationIndex = i + n)
|
||||
length += n
|
||||
}
|
||||
|
||||
private fun addAtInternal(i: Int, element: E) {
|
||||
if (backing != null) {
|
||||
backing.addAtInternal(i, element)
|
||||
array = backing.array
|
||||
// length++ kills translation
|
||||
length = length + 1
|
||||
} else {
|
||||
insertAtInternal(i, 1)
|
||||
array[i] = element
|
||||
}
|
||||
}
|
||||
|
||||
private fun addAllInternal(i: Int, elements: Collection<E>, n: Int) {
|
||||
if (backing != null) {
|
||||
backing.addAllInternal(i, elements, n)
|
||||
array = backing.array
|
||||
length += n
|
||||
} else {
|
||||
insertAtInternal(i, n)
|
||||
var j = 0
|
||||
val it = elements.iterator()
|
||||
while (j < n) {
|
||||
array[i + j] = it.next()
|
||||
j++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeAtInternal(i: Int): E {
|
||||
if (backing != null) {
|
||||
val old = backing.removeAtInternal(i)
|
||||
length--
|
||||
return old
|
||||
} else {
|
||||
val old = array[i]
|
||||
array.copyRange(fromIndex = i + 1, toIndex = offset + length, destinationIndex = i)
|
||||
array.resetAt(offset + length - 1)
|
||||
length--
|
||||
return old
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeRangeInternal(rangeOffset: Int, rangeLength: Int) {
|
||||
if (backing != null) {
|
||||
backing.removeRangeInternal(rangeOffset, rangeLength)
|
||||
} else {
|
||||
array.copyRange(fromIndex = rangeOffset + rangeLength, toIndex = length, destinationIndex = rangeOffset)
|
||||
array.resetRange(fromIndex = length - rangeLength, toIndex = length)
|
||||
}
|
||||
length -= rangeLength
|
||||
}
|
||||
|
||||
private fun retainAllInRangeInternal(rangeOffset: Int, rangeLength: Int, elements: Collection<E>): Int {
|
||||
if (backing != null) {
|
||||
val removed = backing.retainAllInRangeInternal(rangeOffset, rangeLength, elements)
|
||||
length -= removed
|
||||
return removed
|
||||
} else {
|
||||
var i = 0
|
||||
var j = 0
|
||||
while (i < rangeLength) {
|
||||
if (elements.contains(array[rangeOffset + i])) {
|
||||
array[rangeOffset + j++] = array[rangeOffset + i++]
|
||||
} else {
|
||||
// TODO: i++ kills translation.
|
||||
i = i + 1
|
||||
}
|
||||
}
|
||||
val removed = rangeLength - j
|
||||
array.copyRange(fromIndex = rangeOffset + rangeLength, toIndex = length, destinationIndex = rangeOffset + j)
|
||||
array.resetRange(fromIndex = length - removed, toIndex = length)
|
||||
length -= removed
|
||||
return removed
|
||||
}
|
||||
}
|
||||
|
||||
private class Itr<E> : MutableListIterator<E> {
|
||||
private val list: ArrayList<E>
|
||||
private var index: Int
|
||||
private var lastIndex: Int
|
||||
|
||||
constructor(list: ArrayList<E>, index: Int) {
|
||||
this.list = list
|
||||
this.index = index
|
||||
this.lastIndex = -1
|
||||
}
|
||||
|
||||
override fun hasPrevious(): Boolean = index > 0
|
||||
override fun hasNext(): Boolean = index < list.length
|
||||
|
||||
override fun previousIndex(): Int = index - 1
|
||||
override fun nextIndex(): Int = index
|
||||
|
||||
override fun previous(): E {
|
||||
if (index <= 0) throw IndexOutOfBoundsException()
|
||||
lastIndex = --index
|
||||
return list.array[list.offset + lastIndex]
|
||||
}
|
||||
|
||||
override fun next(): E {
|
||||
if (index >= list.length) throw IndexOutOfBoundsException()
|
||||
lastIndex = index++
|
||||
return list.array[list.offset + lastIndex]
|
||||
}
|
||||
|
||||
override fun set(element: E) {
|
||||
list.checkIndex(lastIndex)
|
||||
list.array[list.offset + lastIndex] = element
|
||||
}
|
||||
|
||||
override fun add(element: E) {
|
||||
list.add(index++, element)
|
||||
lastIndex = -1
|
||||
}
|
||||
|
||||
override fun remove() {
|
||||
list.removeAt(lastIndex)
|
||||
index = lastIndex
|
||||
lastIndex = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package kotlin.collections
|
||||
|
||||
/**
|
||||
* Returns an array of objects of the given type with the given [size], initialized with **lateinit** _uninitialized_ values.
|
||||
* Attempts to read _uninitialized_ values from this array work in implementation-dependent manner,
|
||||
* either throwing exception or returning some kind of implementation-specific default value.
|
||||
*/
|
||||
fun <E> arrayOfLateInitElements(size: Int): Array<E> {
|
||||
// TODO: maybe use an empoty array.
|
||||
// return (if (size == 0) emptyArray else Array<Any>(size)) as Array<E>
|
||||
return Array<Any>(size) as Array<E>
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values.
|
||||
* Attempts to read _uninitialized_ values from this array work in implementation-dependent manner,
|
||||
* either throwing exception or returning some kind of implementation-specific default value.
|
||||
*/
|
||||
fun <E> Array<E>.copyOfLateInitElements(newSize: Int): Array<E> {
|
||||
val result = Array<Any>(newSize) as Array<E>
|
||||
this.copyRangeTo(result, 0, if (newSize > this.size) this.size else newSize, 0)
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets an array element at a specified index to some implementation-specific _uninitialized_ value.
|
||||
* In particular, references stored in this element are released and become available for garbage collection.
|
||||
* Attempts to read _uninitialized_ value work in implementation-dependent manner,
|
||||
* either throwing exception or returning some kind of implementation-specific default value.
|
||||
*/
|
||||
fun <E> Array<E>.resetAt(index: Int) {
|
||||
(this as Array<Any?>)[index] = null
|
||||
}
|
||||
|
||||
@SymbolName("Kotlin_Array_fillImpl")
|
||||
external private fun fillImpl(array: Array<Any>, fromIndex: Int, toIndex: Int, value: Any?)
|
||||
|
||||
/**
|
||||
* Resets a range of array elements at a specified [fromIndex] (inclusive) to [toIndex] (exclusive) range of indices
|
||||
* to some implementation-specific _uninitialized_ value.
|
||||
* In particular, references stored in these elements are released and become available for garbage collection.
|
||||
* Attempts to read _uninitialized_ values work in implementation-dependent manner,
|
||||
* either throwing exception or returning some kind of implementation-specific default value.
|
||||
*/
|
||||
fun <E> Array<E>.resetRange(fromIndex: Int, toIndex: Int) {
|
||||
fillImpl(this as Array<Any>, fromIndex, toIndex, null)
|
||||
}
|
||||
|
||||
@SymbolName("Kotlin_Array_copyImpl")
|
||||
external private fun copyImpl(array: Array<Any>, fromIndex: Int,
|
||||
destination: Array<Any>, toIndex: Int, count: Int)
|
||||
|
||||
/**
|
||||
* Copies a range of array elements at a specified [fromIndex] (inclusive) to [toIndex] (exclusive) range of indices
|
||||
* to another [destination] array starting at [destinationIndex].
|
||||
*/
|
||||
fun <E> Array<E>.copyRangeTo(destination: Array<E>, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) {
|
||||
copyImpl(this as Array<Any>, fromIndex, destination as Array<Any>, destinationIndex, toIndex - fromIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a range of array elements at a specified [fromIndex] (inclusive) to [toIndex] (exclusive) range of indices
|
||||
* to another part of this array starting at [destinationIndex].
|
||||
*/
|
||||
fun <E> Array<E>.copyRange(fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) {
|
||||
copyRangeTo(this, fromIndex, toIndex, destinationIndex)
|
||||
}
|
||||
Reference in New Issue
Block a user