1 /*
<lambda>null2 * 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 import android.util.ArrayMap
20
21 typealias IndexedMap<K, V> = ArrayMap<K, V>
22
23 inline fun <K, V> IndexedMap<K, V>.allIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
24 forEachIndexed { index, key, value ->
25 if (!predicate(index, key, value)) {
26 return false
27 }
28 }
29 return true
30 }
31
anyIndexednull32 inline fun <K, V> IndexedMap<K, V>.anyIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
33 forEachIndexed { index, key, value ->
34 if (predicate(index, key, value)) {
35 return true
36 }
37 }
38 return false
39 }
40
copynull41 inline fun <K, V> IndexedMap<K, V>.copy(copyValue: (V) -> V): IndexedMap<K, V> =
42 IndexedMap(this).apply {
43 forEachValueIndexed { index, value ->
44 setValueAt(index, copyValue(value))
45 }
46 }
47
firstNotNullOfOrNullIndexednull48 inline fun <K, V, R> IndexedMap<K, V>.firstNotNullOfOrNullIndexed(transform: (Int, K, V) -> R): R? {
49 forEachIndexed { index, key, value ->
50 transform(index, key, value)?.let { return it }
51 }
52 return null
53 }
54
forEachIndexednull55 inline fun <K, V> IndexedMap<K, V>.forEachIndexed(action: (Int, K, V) -> Unit) {
56 for (index in 0 until size) {
57 action(index, keyAt(index), valueAt(index))
58 }
59 }
60
forEachKeyIndexednull61 inline fun <K, V> IndexedMap<K, V>.forEachKeyIndexed(action: (Int, K) -> Unit) {
62 for (index in 0 until size) {
63 action(index, keyAt(index))
64 }
65 }
66
forEachReversedIndexednull67 inline fun <K, V> IndexedMap<K, V>.forEachReversedIndexed(action: (Int, K, V) -> Unit) {
68 for (index in lastIndex downTo 0) {
69 action(index, keyAt(index), valueAt(index))
70 }
71 }
72
forEachValueIndexednull73 inline fun <K, V> IndexedMap<K, V>.forEachValueIndexed(action: (Int, V) -> Unit) {
74 for (index in 0 until size) {
75 action(index, valueAt(index))
76 }
77 }
78
getOrPutnull79 inline fun <K, V> IndexedMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
80 get(key)?.let { return it }
81 return defaultValue().also { put(key, it) }
82 }
83
84 @Suppress("NOTHING_TO_INLINE")
getWithDefaultnull85 inline fun <K, V> IndexedMap<K, V>?.getWithDefault(key: K, defaultValue: V): V {
86 this ?: return defaultValue
87 val index = indexOfKey(key)
88 return if (index >= 0) valueAt(index) else defaultValue
89 }
90
91 inline val <K, V> IndexedMap<K, V>.lastIndex: Int
92 get() = size - 1
93
94 @Suppress("NOTHING_TO_INLINE")
minusAssignnull95 inline operator fun <K, V> IndexedMap<K, V>.minusAssign(key: K) {
96 remove(key)
97 }
98
noneIndexednull99 inline fun <K, V> IndexedMap<K, V>.noneIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
100 forEachIndexed { index, key, value ->
101 if (predicate(index, key, value)) {
102 return false
103 }
104 }
105 return true
106 }
107
108 @Suppress("NOTHING_TO_INLINE")
putWithDefaultnull109 inline fun <K, V> IndexedMap<K, V>.putWithDefault(key: K, value: V, defaultValue: V): V {
110 val index = indexOfKey(key)
111 if (index >= 0) {
112 val oldValue = valueAt(index)
113 if (value != oldValue) {
114 if (value == defaultValue) {
115 removeAt(index)
116 } else {
117 setValueAt(index, value)
118 }
119 }
120 return oldValue
121 } else {
122 if (value != defaultValue) {
123 put(key, value)
124 }
125 return defaultValue
126 }
127 }
128
removeAllIndexednull129 inline fun <K, V> IndexedMap<K, V>.removeAllIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
130 var isChanged = false
131 forEachReversedIndexed { index, key, value ->
132 if (predicate(index, key, value)) {
133 removeAt(index)
134 isChanged = true
135 }
136 }
137 return isChanged
138 }
139
retainAllIndexednull140 inline fun <K, V> IndexedMap<K, V>.retainAllIndexed(predicate: (Int, K, V) -> Boolean): Boolean {
141 var isChanged = false
142 forEachReversedIndexed { index, key, value ->
143 if (!predicate(index, key, value)) {
144 removeAt(index)
145 isChanged = true
146 }
147 }
148 return isChanged
149 }
150
mapIndexednull151 inline fun <K, V, R> IndexedMap<K, V>.mapIndexed(transform: (Int, K, V) -> R): IndexedList<R> =
152 IndexedList<R>().also { destination ->
153 forEachIndexed { index, key, value ->
154 transform(index, key, value).let { destination += it }
155 }
156 }
157
mapNotNullIndexednull158 inline fun <K, V, R> IndexedMap<K, V>.mapNotNullIndexed(
159 transform: (Int, K, V) -> R?
160 ): IndexedList<R> =
161 IndexedList<R>().also { destination ->
162 forEachIndexed { index, key, value ->
163 transform(index, key, value)?.let { destination += it }
164 }
165 }
166
mapNotNullIndexedToSetnull167 inline fun <K, V, R> IndexedMap<K, V>.mapNotNullIndexedToSet(
168 transform: (Int, K, V) -> R?
169 ): IndexedSet<R> =
170 IndexedSet<R>().also { destination ->
171 forEachIndexed { index, key, value ->
172 transform(index, key, value)?.let { destination += it }
173 }
174 }
175
176 @Suppress("NOTHING_TO_INLINE")
setnull177 inline operator fun <K, V> IndexedMap<K, V>.set(key: K, value: V) {
178 put(key, value)
179 }
180