From 28911df1d0505afa1698dc23d8ff7d5c00973e25 Mon Sep 17 00:00:00 2001 From: Marko Devcic Date: Tue, 27 Sep 2016 18:31:49 +0200 Subject: [PATCH 1/2] add sparse array forEach extensions --- .../src/test/java/SparseArraysTest | 95 +++++++++++++++++++ .../common/src/collections/SparseArrays.kt | 66 +++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 anko/library/robolectricTests/src/test/java/SparseArraysTest create mode 100644 anko/library/static/common/src/collections/SparseArrays.kt diff --git a/anko/library/robolectricTests/src/test/java/SparseArraysTest b/anko/library/robolectricTests/src/test/java/SparseArraysTest new file mode 100644 index 00000000..a92fd426 --- /dev/null +++ b/anko/library/robolectricTests/src/test/java/SparseArraysTest @@ -0,0 +1,95 @@ +package test + +import android.util.SparseArray +import android.util.SparseBooleanArray +import android.util.SparseIntArray +import android.util.SparseLongArray +import com.mysugr.android.forEach +import com.mysugr.logbook.BuildConfig +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricGradleTestRunner +import org.robolectric.annotation.Config + + +@RunWith(RobolectricGradleTestRunner::class) +@Config(constants = BuildConfig::class) +public class SparseArraysTest { + + @Test + fun testGenericForEachRandomNumbers() { + val sa = SparseArray() + + sa.put(2, 2.toString()) + sa.put(8, 8.toString()) + sa.put(5, 5.toString()) + sa.put(10, 10.toString()) + sa.put(7, 7.toString()) + sa.put(4, 4.toString()) + sa.put(9, 9.toString()) + sa.put(1, 1.toString()) + sa.put(3, 3.toString()) + sa.put(6, 6.toString()) + + var invokeCount = 0 + sa.forEach { k, v -> + invokeCount++ + Assert.assertEquals(k.toString(), v) + } + + Assert.assertEquals(invokeCount, sa.size()) + } + + @Test + fun testGenericEmptyArray() { + val sa = SparseArray() + sa.forEach { k, v -> throw IllegalStateException("should not be called on an empty array") } + } + + @Test + fun testBooleanArrayForEach() { + val sa = SparseBooleanArray() + + for (i in 1..101) { + sa.put(i, i % 2 == 0) + } + + var invokeCount = 0 + sa.forEach { k, v -> + invokeCount++ + Assert.assertEquals(k % 2 == 0, v ) + } + + Assert.assertEquals(invokeCount, sa.size()) + } + + @Test + fun testBooleanEmptyArray() { + val sa = SparseBooleanArray() + sa.forEach { k, v -> throw IllegalStateException("should not be called on an empty array") } + } + + @Test + fun testIntArrayForEach() { + val sa = SparseIntArray() + + for (i in 1..101) { + sa.put(i, i * 10) + } + + var invokeCount = 0 + sa.forEach { k, v -> + invokeCount++ + Assert.assertEquals(k * 10, v ) + } + + Assert.assertEquals(invokeCount, sa.size()) + } + + @Test + fun testIntEmptyArray() { + val sa = SparseIntArray() + sa.forEach { k, v -> throw IllegalStateException("should not be called on an empty array") } + } +} \ No newline at end of file diff --git a/anko/library/static/common/src/collections/SparseArrays.kt b/anko/library/static/common/src/collections/SparseArrays.kt new file mode 100644 index 00000000..1eb6b96a --- /dev/null +++ b/anko/library/static/common/src/collections/SparseArrays.kt @@ -0,0 +1,66 @@ +/* + * Copyright 2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package collections + + +import android.util.SparseArray +import android.util.SparseBooleanArray +import android.util.SparseIntArray +import java.util.* + + +/** + * Iterate the receiver [SparseArray] + * @action an action to invoke on each key value pair + * @throws [ConcurrentModificationException] if modified while iterating + */ +inline fun SparseArray.forEach(action: (Int, E) -> Unit) { + val size = this.size() + for (i in 0..size - 1) { + if (size != this.size()) throw ConcurrentModificationException() + action(this.keyAt(i), this.valueAt(i)) + } +} + +/** + * Iterate the receiver [SparseBooleanArray] + * @action an action to invoke on each key value pair + * @throws [ConcurrentModificationException] if modified while iterating + */ +inline fun SparseBooleanArray.forEach(action: (Int, Boolean) -> Unit) { + val size = this.size() + if (size != this.size()) throw ConcurrentModificationException() + for (i in 0..size - 1) { + if (size != this.size()) throw ConcurrentModificationException() + action(this.keyAt(i), this.valueAt(i)) + } +} + +/** + * Iterate the receiver [SparseIntArray] + * @action an action to invoke on each key value pair + * @throws [ConcurrentModificationException] if modified while iterating + */ +inline fun SparseIntArray.forEach(action: (Int, Int) -> Unit) { + val size = this.size() + for (i in 0..size - 1) { + if (size != this.size()) throw ConcurrentModificationException() + action(this.keyAt(i), this.valueAt(i)) + } +} + + From d157546c43683a7454b3bb01aa9379c8a5c4f599 Mon Sep 17 00:00:00 2001 From: Marko Devcic Date: Wed, 28 Sep 2016 18:27:17 +0200 Subject: [PATCH 2/2] remove redundant size check --- anko/library/static/common/src/collections/SparseArrays.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/anko/library/static/common/src/collections/SparseArrays.kt b/anko/library/static/common/src/collections/SparseArrays.kt index 1eb6b96a..8a77d2f7 100644 --- a/anko/library/static/common/src/collections/SparseArrays.kt +++ b/anko/library/static/common/src/collections/SparseArrays.kt @@ -43,7 +43,6 @@ inline fun SparseArray.forEach(action: (Int, E) -> Unit) { */ inline fun SparseBooleanArray.forEach(action: (Int, Boolean) -> Unit) { val size = this.size() - if (size != this.size()) throw ConcurrentModificationException() for (i in 0..size - 1) { if (size != this.size()) throw ConcurrentModificationException() action(this.keyAt(i), this.valueAt(i))