1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.permission.access.collection 18 19 class IndexedListSet<T> private constructor( 20 private val list: ArrayList<T> 21 ) : MutableSet<T> { 22 constructor() : this(ArrayList()) 23 24 override val size: Int 25 get() = list.size 26 27 override fun contains(element: T): Boolean = list.contains(element) 28 29 override fun isEmpty(): Boolean = list.isEmpty() 30 31 override fun iterator(): MutableIterator<T> = list.iterator() 32 33 override fun containsAll(elements: Collection<T>): Boolean { 34 throw NotImplementedError() 35 } 36 37 fun elementAt(index: Int): T = list[index] 38 39 fun indexOf(element: T): Int = list.indexOf(element) 40 41 override fun add(element: T): Boolean = 42 if (list.contains(element)) { 43 false 44 } else { 45 list.add(element) 46 true 47 } 48 49 override fun remove(element: T): Boolean = list.remove(element) 50 51 override fun clear() { 52 list.clear() 53 } 54 55 override fun addAll(elements: Collection<T>): Boolean { 56 throw NotImplementedError() 57 } 58 59 override fun removeAll(elements: Collection<T>): Boolean { 60 throw NotImplementedError() 61 } 62 63 override fun retainAll(elements: Collection<T>): Boolean { 64 throw NotImplementedError() 65 } 66 67 fun removeAt(index: Int): T? = list.removeAt(index) 68 69 fun copy(): IndexedListSet<T> = IndexedListSet(ArrayList(list)) 70 } 71 72 inline fun <T> IndexedListSet<T>.allIndexed(predicate: (Int, T) -> Boolean): Boolean { 73 forEachIndexed { index, element -> 74 if (!predicate(index, element)) { 75 return false 76 } 77 } 78 return true 79 } 80 81 inline fun <T> IndexedListSet<T>.anyIndexed(predicate: (Int, T) -> Boolean): Boolean { 82 forEachIndexed { index, element -> 83 if (predicate(index, element)) { 84 return true 85 } 86 } 87 return false 88 } 89 90 inline fun <T> IndexedListSet<T>.forEachIndexed(action: (Int, T) -> Unit) { 91 for (index in indices) { 92 action(index, elementAt(index)) 93 } 94 } 95 96 inline fun <T> IndexedListSet<T>.forEachReversedIndexed(action: (Int, T) -> Unit) { 97 for (index in lastIndex downTo 0) { 98 action(index, elementAt(index)) 99 } 100 } 101 102 inline val <T> IndexedListSet<T>.lastIndex: Int 103 get() = size - 1 104 105 @Suppress("NOTHING_TO_INLINE") 106 inline operator fun <T> IndexedListSet<T>.minus(element: T): IndexedListSet<T> = 107 copy().apply { this -= element } 108 109 @Suppress("NOTHING_TO_INLINE") 110 inline operator fun <T> IndexedListSet<T>.minusAssign(element: T) { 111 remove(element) 112 } 113 114 inline fun <T> IndexedListSet<T>.noneIndexed(predicate: (Int, T) -> Boolean): Boolean { 115 forEachIndexed { index, element -> 116 if (predicate(index, element)) { 117 return false 118 } 119 } 120 return true 121 } 122 123 @Suppress("NOTHING_TO_INLINE") 124 inline operator fun <T> IndexedListSet<T>.plus(element: T): IndexedListSet<T> = 125 copy().apply { this += element } 126 127 @Suppress("NOTHING_TO_INLINE") 128 inline operator fun <T> IndexedListSet<T>.plusAssign(element: T) { 129 add(element) 130 } 131 132 inline fun <T> IndexedListSet<T>.removeAllIndexed(predicate: (Int, T) -> Boolean): Boolean { 133 var isChanged = false 134 forEachReversedIndexed { index, element -> 135 if (predicate(index, element)) { 136 removeAt(index) 137 isChanged = true 138 } 139 } 140 return isChanged 141 } 142 143 inline fun <T> IndexedListSet<T>.retainAllIndexed(predicate: (Int, T) -> Boolean): Boolean { 144 var isChanged = false 145 forEachReversedIndexed { index, element -> 146 if (!predicate(index, element)) { 147 removeAt(index) 148 isChanged = true 149 } 150 } 151 return isChanged 152 } 153