aboutsummaryrefslogtreecommitdiffstats
path: root/kotlinx-coroutines-core/native/src/internal/CopyOnWriteList.kt
blob: c81f6530e03da5d38ba55d13d94a47c0211a2dde (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

package kotlinx.coroutines.internal

@Suppress("UNCHECKED_CAST")
internal class CopyOnWriteList<E>(private var array: Array<Any?> = arrayOfNulls(4)) : AbstractMutableList<E>() {

    private var _size = 0
    override val size: Int get() = _size

    override fun add(element: E): Boolean {
        val newSize = if (_size == array.size) array.size * 2 else  array.size
        val update = array.copyOf(newSize)
        update[_size++] = element
        array = update
        return true
    }

    override fun add(index: Int, element: E) {
        rangeCheck(index)
        val update = arrayOfNulls<Any?>(if (array.size == _size) array.size * 2 else array.size)
        array.copyInto(
            destination = update,
            endIndex = index
        )
        update[index] = element
        array.copyInto(
            destination = update,
            destinationOffset = index + 1,
            startIndex = index,
            endIndex = _size + 1
        )
        ++_size
        array = update
    }

    override fun remove(element: E): Boolean {
        val index = array.indexOf(element as Any)
        if (index == -1) {
            return false
        }

        removeAt(index)
        return true
    }

    override fun removeAt(index: Int): E {
        rangeCheck(index)
        modCount++
        val n = array.size
        val element = array[index]
        val update = arrayOfNulls<Any>(n)
        array.copyInto(
            destination = update,
            endIndex = index
        )
        array.copyInto(
            destination = update,
            destinationOffset = index,
            startIndex = index + 1,
            endIndex = n
        )
        array = update
        --_size
        return element as E
    }

    override fun iterator(): MutableIterator<E> = IteratorImpl(array as Array<E>, size)

    override fun listIterator(): MutableListIterator<E> = throw UnsupportedOperationException("Operation is not supported")

    override fun listIterator(index: Int): MutableListIterator<E> = throw UnsupportedOperationException("Operation is not supported")

    override fun isEmpty(): Boolean = size == 0

    override fun set(index: Int, element: E): E = throw UnsupportedOperationException("Operation is not supported")

    override fun get(index: Int): E = array[rangeCheck(index)]!! as E

    private class IteratorImpl<E>(private var array: Array<E>, private val size: Int) : MutableIterator<E> {

        private var current = 0

        override fun hasNext(): Boolean = current != size

        override fun next(): E {
            if (!hasNext()) {
                throw NoSuchElementException()
            }

            return array[current++]!!
        }

        override fun remove() = throw UnsupportedOperationException("Operation is not supported")
    }

    private fun rangeCheck(index: Int) = index.apply {
        if (index < 0 || index >= _size) {
            throw IndexOutOfBoundsException("index: $index, size: $size")
        }
    }
}