From 512d986006863837d9891d4a6378be9651fe9743 Mon Sep 17 00:00:00 2001 From: Abduqodiri Qurbonzoda Date: Tue, 29 Jan 2019 13:50:32 +0300 Subject: [PATCH] Implement index-requesting extension functions for UArrays Contains implementations of `indexOf`, `lastIndexOf`, `indexOfFirst`, `indexOfLast`, `lastIndex` and `indices` extension functions. --- .../stdlib/common/src/generated/_UArrays.kt | 232 ++++++++++++++++++ .../test/collections/UnsignedArraysTest.kt | 47 ++++ .../kotlin-stdlib-gen/src/templates/Arrays.kt | 12 +- .../src/templates/Elements.kt | 34 ++- 4 files changed, 317 insertions(+), 8 deletions(-) diff --git a/libraries/stdlib/common/src/generated/_UArrays.kt b/libraries/stdlib/common/src/generated/_UArrays.kt index 302741a473f..709fbad1c78 100644 --- a/libraries/stdlib/common/src/generated/_UArrays.kt +++ b/libraries/stdlib/common/src/generated/_UArrays.kt @@ -215,6 +215,166 @@ public inline operator fun UShortArray.component5(): UShort { return get(4) } +/** + * Returns first index of [element], or -1 if the array does not contain element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UIntArray.indexOf(element: UInt): Int { + return storage.indexOf(element.toInt()) +} + +/** + * Returns first index of [element], or -1 if the array does not contain element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun ULongArray.indexOf(element: ULong): Int { + return storage.indexOf(element.toLong()) +} + +/** + * Returns first index of [element], or -1 if the array does not contain element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UByteArray.indexOf(element: UByte): Int { + return storage.indexOf(element.toByte()) +} + +/** + * Returns first index of [element], or -1 if the array does not contain element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UShortArray.indexOf(element: UShort): Int { + return storage.indexOf(element.toShort()) +} + +/** + * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UIntArray.indexOfFirst(predicate: (UInt) -> Boolean): Int { + return storage.indexOfFirst { predicate(it.toUInt()) } +} + +/** + * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun ULongArray.indexOfFirst(predicate: (ULong) -> Boolean): Int { + return storage.indexOfFirst { predicate(it.toULong()) } +} + +/** + * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UByteArray.indexOfFirst(predicate: (UByte) -> Boolean): Int { + return storage.indexOfFirst { predicate(it.toUByte()) } +} + +/** + * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UShortArray.indexOfFirst(predicate: (UShort) -> Boolean): Int { + return storage.indexOfFirst { predicate(it.toUShort()) } +} + +/** + * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UIntArray.indexOfLast(predicate: (UInt) -> Boolean): Int { + return storage.indexOfLast { predicate(it.toUInt()) } +} + +/** + * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun ULongArray.indexOfLast(predicate: (ULong) -> Boolean): Int { + return storage.indexOfLast { predicate(it.toULong()) } +} + +/** + * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UByteArray.indexOfLast(predicate: (UByte) -> Boolean): Int { + return storage.indexOfLast { predicate(it.toUByte()) } +} + +/** + * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UShortArray.indexOfLast(predicate: (UShort) -> Boolean): Int { + return storage.indexOfLast { predicate(it.toUShort()) } +} + +/** + * Returns last index of [element], or -1 if the array does not contain element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UIntArray.lastIndexOf(element: UInt): Int { + return storage.lastIndexOf(element.toInt()) +} + +/** + * Returns last index of [element], or -1 if the array does not contain element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun ULongArray.lastIndexOf(element: ULong): Int { + return storage.lastIndexOf(element.toLong()) +} + +/** + * Returns last index of [element], or -1 if the array does not contain element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UByteArray.lastIndexOf(element: UByte): Int { + return storage.lastIndexOf(element.toByte()) +} + +/** + * Returns last index of [element], or -1 if the array does not contain element. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline fun UShortArray.lastIndexOf(element: UShort): Int { + return storage.lastIndexOf(element.toShort()) +} + /** * Returns a random element from this array. * @@ -775,6 +935,78 @@ public inline fun UShortArray.copyOfRange(fromIndex: Int, toIndex: Int): UShortA return UShortArray(storage.copyOfRange(fromIndex, toIndex)) } +/** + * Returns the range of valid indices for the array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline val UIntArray.indices: IntRange + get() = storage.indices + +/** + * Returns the range of valid indices for the array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline val ULongArray.indices: IntRange + get() = storage.indices + +/** + * Returns the range of valid indices for the array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline val UByteArray.indices: IntRange + get() = storage.indices + +/** + * Returns the range of valid indices for the array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline val UShortArray.indices: IntRange + get() = storage.indices + +/** + * Returns the last valid index for the array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline val UIntArray.lastIndex: Int + get() = storage.lastIndex + +/** + * Returns the last valid index for the array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline val ULongArray.lastIndex: Int + get() = storage.lastIndex + +/** + * Returns the last valid index for the array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline val UByteArray.lastIndex: Int + get() = storage.lastIndex + +/** + * Returns the last valid index for the array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public inline val UShortArray.lastIndex: Int + get() = storage.lastIndex + /** * Returns an array containing all elements of the original array and then the given [element]. */ diff --git a/libraries/stdlib/test/collections/UnsignedArraysTest.kt b/libraries/stdlib/test/collections/UnsignedArraysTest.kt index 662280bab6c..ae31cc1b961 100644 --- a/libraries/stdlib/test/collections/UnsignedArraysTest.kt +++ b/libraries/stdlib/test/collections/UnsignedArraysTest.kt @@ -238,4 +238,51 @@ class UnsignedArraysTest { assertArrayContentEquals(uintArrayOf(1u, 2u, 3u, 4u), uintArrayOf(1u, 2u) + uintArrayOf(3u, 4u)) } + @Test + fun indexOf() { + expect(-1) { ubyteArrayOf(1, 2, 3).indexOf(0) } + expect(0) { ushortArrayOf(1, 2, 3).indexOf(1) } + expect(1) { uintArrayOf(1, 2, 3).indexOf(2) } + expect(2) { ulongArrayOf(1, 2, 3).indexOf(3) } + } + + @Test + fun indexOfFirst() { + expect(-1) { ubyteArrayOf(1, 2, 3).indexOfFirst { it == 5.toUByte() } } + expect(0) { ushortArrayOf(1, 2, 3).indexOfFirst { it % 2u == 1u } } + expect(1) { uintArrayOf(1, 2, 3).indexOfFirst { it % 2u == 0u } } + expect(2) { ulongArrayOf(1, 2, 3).indexOfFirst { it == 3.toULong() } } + } + + @Test + fun lastIndexOf() { + expect(-1) { ubyteArrayOf(1, 2, 3).lastIndexOf(0) } + expect(0) { ushortArrayOf(1, 2, 3).lastIndexOf(1) } + expect(1) { uintArrayOf(2, 2, 3).lastIndexOf(2) } + expect(2) { ulongArrayOf(3, 2, 3).lastIndexOf(3) } + } + + @Test + fun indexOfLast() { + expect(-1) { ubyteArrayOf(1, 2, 3).indexOfLast { it == 5.toUByte() } } + expect(2) { ushortArrayOf(1, 2, 3).indexOfLast { it % 2u == 1u } } + expect(1) { uintArrayOf(1, 2, 3).indexOfLast { it % 2u == 0u } } + expect(0) { ulongArrayOf(1, 2, 3).indexOfLast { it == 1.toULong() } } + } + + @Test + fun indices() { + expect(0 until 0) { ubyteArrayOf().indices } + expect(0 until 1) { ushortArrayOf(1).indices } + expect(0 until 2) { uintArrayOf(1, 2).indices } + expect(0 until 3) { ulongArrayOf(1, 2, 3).indices } + } + + @Test + fun lastIndex() { + expect(-1) { ubyteArrayOf().lastIndex } + expect(0) { ushortArrayOf(1).lastIndex } + expect(1) { uintArrayOf(1, 2).lastIndex } + expect(2) { ulongArrayOf(1, 2, 3).lastIndex } + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt index f17eb6516ef..65a9e25ed53 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt @@ -44,23 +44,31 @@ object ArrayOps : TemplateGroupBase() { val f_lastIndex = pval("lastIndex") { - include(ArraysOfObjects, ArraysOfPrimitives) + include(ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) } builder { doc { "Returns the last valid index for the array." } returns("Int") body { "get() = size - 1" } + specialFor(ArraysOfUnsigned) { + inlineOnly() + body { "get() = storage.lastIndex" } + } } val f_indices = pval("indices") { - include(ArraysOfObjects, ArraysOfPrimitives) + include(ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned) } builder { doc { "Returns the range of valid indices for the array." } returns("IntRange") body { "get() = IntRange(0, lastIndex)" } + specialFor(ArraysOfUnsigned) { + inlineOnly() + body { "get() = storage.indices" } + } } val f_contentEquals = fn("contentEquals(other: SELF)") { diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt index 93fd838ab70..a94d9d3161f 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Elements.kt @@ -50,7 +50,7 @@ object Elements : TemplateGroupBase() { } val f_indexOf = fn("indexOf(element: T)") { - include(Iterables, Sequences, ArraysOfObjects, ArraysOfPrimitives, Lists) + include(Iterables, Sequences, ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned, Lists) } builder { doc { "Returns first index of [element], or -1 if the ${f.collection} does not contain element." } typeParam("@kotlin.internal.OnlyInputTypes T") @@ -98,13 +98,19 @@ object Elements : TemplateGroupBase() { } } return -1 - """ + """ } body(Lists) { "return indexOf(element)" } + + specialFor(ArraysOfUnsigned) { + inlineOnly() + val signedPrimitiveName = primitive!!.name.drop(1) + body { "return storage.indexOf(element.to$signedPrimitiveName())" } + } } val f_lastIndexOf = fn("lastIndexOf(element: T)") { - include(Iterables, Sequences, ArraysOfObjects, ArraysOfPrimitives, Lists) + include(Iterables, Sequences, ArraysOfObjects, ArraysOfPrimitives, ArraysOfUnsigned, Lists) } builder { doc { "Returns last index of [element], or -1 if the ${f.collection} does not contain element." } typeParam("@kotlin.internal.OnlyInputTypes T") @@ -153,14 +159,20 @@ object Elements : TemplateGroupBase() { } } return -1 - """ + """ } body(Lists) { "return lastIndexOf(element)" } + + specialFor(ArraysOfUnsigned) { + inlineOnly() + val signedPrimitiveName = primitive!!.name.drop(1) + body { "return storage.lastIndexOf(element.to$signedPrimitiveName())" } + } } val f_indexOfFirst = fn("indexOfFirst(predicate: (T) -> Boolean)") { includeDefault() - include(CharSequences, Lists) + include(CharSequences, Lists, ArraysOfUnsigned) } builder { inline() @@ -189,11 +201,16 @@ object Elements : TemplateGroupBase() { return -1 """ } + + specialFor(ArraysOfUnsigned) { + inlineOnly() + body { "return storage.indexOfFirst { predicate(it.to${primitive!!.name}()) }" } + } } val f_indexOfLast = fn("indexOfLast(predicate: (T) -> Boolean)") { includeDefault() - include(CharSequences, Lists) + include(CharSequences, Lists, ArraysOfUnsigned) } builder { inline() @@ -234,6 +251,11 @@ object Elements : TemplateGroupBase() { return -1 """ } + + specialFor(ArraysOfUnsigned) { + inlineOnly() + body { "return storage.indexOfLast { predicate(it.to${primitive!!.name}()) }" } + } } val f_elementAt = fn("elementAt(index: Int)") {