1 /*
2 * Copyright (C) 2023 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.immutable
18
19 import android.util.SparseArray
20
21 /** Immutable map with index-based access and [Int] keys. */
22 sealed class IntMap<T>(internal val array: SparseArray<T>) : Immutable<MutableIntMap<T>> {
23 val size: Int
24 get() = array.size()
25
isEmptynull26 fun isEmpty(): Boolean = array.size() == 0
27
28 operator fun contains(key: Int): Boolean = array.contains(key)
29
30 operator fun get(key: Int): T? = array.get(key)
31
32 fun indexOfKey(key: Int): Int = array.indexOfKey(key)
33
34 fun keyAt(index: Int): Int = array.keyAt(index)
35
36 fun valueAt(index: Int): T = array.valueAt(index)
37
38 override fun toMutable(): MutableIntMap<T> = MutableIntMap(this)
39
40 override fun toString(): String = array.toString()
41 }
42
43 /** Mutable map with index-based access and [Int] keys. */
44 class MutableIntMap<T>(array: SparseArray<T> = SparseArray()) : IntMap<T>(array) {
45 constructor(intMap: IntMap<T>) : this(intMap.array.clone())
46
47 fun put(key: Int, value: T): T? = array.putReturnOld(key, value)
48
49 fun remove(key: Int): T? = array.removeReturnOld(key).also { array.gc() }
50
51 fun clear() {
52 array.clear()
53 }
54
55 fun putAt(index: Int, value: T): T = array.setValueAtReturnOld(index, value)
56
57 fun removeAt(index: Int): T = array.removeAtReturnOld(index).also { array.gc() }
58 }
59
putReturnOldnull60 internal fun <T> SparseArray<T>.putReturnOld(key: Int, value: T): T? {
61 val index = indexOfKey(key)
62 return if (index >= 0) {
63 val oldValue = valueAt(index)
64 setValueAt(index, value)
65 oldValue
66 } else {
67 put(key, value)
68 null
69 }
70 }
71
72 // SparseArray.removeReturnOld() is @hide, so a backup once we move to APIs.
73 @Suppress("EXTENSION_SHADOWED_BY_MEMBER")
removeReturnOldnull74 internal fun <T> SparseArray<T>.removeReturnOld(key: Int): T? {
75 val index = indexOfKey(key)
76 return if (index >= 0) {
77 val oldValue = valueAt(index)
78 removeAt(index)
79 oldValue
80 } else {
81 null
82 }
83 }
84
setValueAtReturnOldnull85 internal fun <T> SparseArray<T>.setValueAtReturnOld(index: Int, value: T): T {
86 val oldValue = valueAt(index)
87 setValueAt(index, value)
88 return oldValue
89 }
90
removeAtReturnOldnull91 internal fun <T> SparseArray<T>.removeAtReturnOld(index: Int): T {
92 val oldValue = valueAt(index)
93 removeAt(index)
94 return oldValue
95 }
96
gcnull97 internal fun <T> SparseArray<T>.gc() {
98 size()
99 }
100