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.SparseArray
20
21 typealias IntMap<T> = SparseArray<T>
22
23 inline fun <T> IntMap<T>.allIndexed(predicate: (Int, Int, T) -> 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 <T> IntMap<T>.anyIndexed(predicate: (Int, Int, T) -> 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 <T> IntMap<T>.copy(copyValue: (T) -> T): IntMap<T> =
42 this.clone().apply {
43 forEachValueIndexed { index, value ->
44 setValueAt(index, copyValue(value))
45 }
46 }
47
firstNotNullOfOrNullIndexednull48 inline fun <T, R> IntMap<T>.firstNotNullOfOrNullIndexed(transform: (Int, Int, T) -> R): R? {
49 forEachIndexed { index, key, value ->
50 transform(index, key, value)?.let { return it }
51 }
52 return null
53 }
54
forEachIndexednull55 inline fun <T> IntMap<T>.forEachIndexed(action: (Int, Int, T) -> Unit) {
56 for (index in 0 until size) {
57 action(index, keyAt(index), valueAt(index))
58 }
59 }
60
forEachKeyIndexednull61 inline fun <T> IntMap<T>.forEachKeyIndexed(action: (Int, Int) -> Unit) {
62 for (index in 0 until size) {
63 action(index, keyAt(index))
64 }
65 }
66
forEachReversedIndexednull67 inline fun <T> IntMap<T>.forEachReversedIndexed(action: (Int, Int, T) -> Unit) {
68 for (index in lastIndex downTo 0) {
69 action(index, keyAt(index), valueAt(index))
70 }
71 }
72
forEachValueIndexednull73 inline fun <T> IntMap<T>.forEachValueIndexed(action: (Int, T) -> Unit) {
74 for (index in 0 until size) {
75 action(index, valueAt(index))
76 }
77 }
78
getOrPutnull79 inline fun <T> IntMap<T>.getOrPut(key: Int, defaultValue: () -> T): T {
80 get(key)?.let { return it }
81 return defaultValue().also { put(key, it) }
82 }
83
84 @Suppress("NOTHING_TO_INLINE")
getWithDefaultnull85 inline fun <T> IntMap<T>?.getWithDefault(key: Int, defaultValue: T): T {
86 this ?: return defaultValue
87 val index = indexOfKey(key)
88 return if (index >= 0) valueAt(index) else defaultValue
89 }
90
91 inline val <T> IntMap<T>.lastIndex: Int
92 get() = size - 1
93
94 @Suppress("NOTHING_TO_INLINE")
minusAssignnull95 inline operator fun <T> IntMap<T>.minusAssign(key: Int) {
96 remove(key)
97 }
98
noneIndexednull99 inline fun <T> IntMap<T>.noneIndexed(predicate: (Int, Int, T) -> 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 <T> IntMap<T>.putWithDefault(key: Int, value: T, defaultValue: T): T {
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
129 // SparseArray.removeReturnOld() is @hide, so a backup once we move to APIs.
removeReturnOldnull130 fun <T> IntMap<T>.removeReturnOld(key: Int): T? {
131 val index = indexOfKey(key)
132 return if (index >= 0) {
133 val oldValue = valueAt(index)
134 removeAt(index)
135 oldValue
136 } else {
137 null
138 }
139 }
140
removeAllIndexednull141 inline fun <T> IntMap<T>.removeAllIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
142 var isChanged = false
143 forEachReversedIndexed { index, key, value ->
144 if (predicate(index, key, value)) {
145 removeAt(index)
146 isChanged = true
147 }
148 }
149 return isChanged
150 }
151
retainAllIndexednull152 inline fun <T> IntMap<T>.retainAllIndexed(predicate: (Int, Int, T) -> Boolean): Boolean {
153 var isChanged = false
154 forEachReversedIndexed { index, key, value ->
155 if (!predicate(index, key, value)) {
156 removeAt(index)
157 isChanged = true
158 }
159 }
160 return isChanged
161 }
162
163 inline val <T> IntMap<T>.size: Int
164 get() = size()
165