From 374397d03faf14dcdf10a6a31d54bf58f85d9bbb Mon Sep 17 00:00:00 2001 From: Pavel Punegov Date: Wed, 16 May 2018 18:39:49 +0300 Subject: [PATCH] Common stdlib - adds actual matching expect declarations - removes duplicates - rewrite collections - add MPP and experimental compiler options --- backend.native/build.gradle | 5 + .../jetbrains/kotlin/backend/konan/ir/Ir.kt | 16 +- .../backend/konan/lower/LateinitLowering.kt | 4 +- .../tests/runtime/text/string_builder0.kt | 6 +- .../text/harmony_regex/PatternTest2.kt | 2 +- runtime/src/main/kotlin/konan/concurrent.kt | 2 +- .../src/main/kotlin/konan/internal/Char.kt | 50 - .../main/kotlin/konan/internal/Coroutines.kt | 53 - .../src/main/kotlin/konan/internal/Strings.kt | 45 +- runtime/src/main/kotlin/kotlin/Arrays.kt | 13866 ---------------- runtime/src/main/kotlin/kotlin/Comparable.kt | 2 +- .../IndexedValue.kt => Comparator.kt} | 20 +- runtime/src/main/kotlin/kotlin/Exceptions.kt | 126 +- .../src/main/kotlin/kotlin/KotlinVersion.kt | 89 - runtime/src/main/kotlin/kotlin/Lazy.kt | 165 +- runtime/src/main/kotlin/kotlin/Numbers.kt | 24 +- .../kotlin/collections/AbstractIterator.kt | 85 - ...ection.kt => AbstractMutableCollection.kt} | 34 - ...AbstractList.kt => AbstractMutableList.kt} | 151 +- .../kotlin/kotlin/collections/AbstractSet.kt | 59 - .../kotlin/kotlin/collections/ArrayList.kt | 62 +- .../main/kotlin/kotlin/collections/Arrays.kt | 1344 +- .../kotlin/kotlin/collections/Collections.kt | 2634 +-- .../kotlin/kotlin/collections/Grouping.kt | 267 - .../main/kotlin/kotlin/collections/HashMap.kt | 62 +- .../main/kotlin/kotlin/collections/HashSet.kt | 43 +- .../kotlin/kotlin/collections/Iterables.kt | 98 - .../kotlin/kotlin/collections/Iterators.kt | 28 - .../kotlin/kotlin/collections/MapAccessors.kt | 55 - .../kotlin/collections/MapWithDefault.kt | 110 - .../main/kotlin/kotlin/collections/Maps.kt | 860 +- .../kotlin/collections/MutableCollections.kt | 305 +- .../kotlin/kotlin/collections/RandomAccess.kt | 3 +- .../kotlin/collections/ReversedViews.kt | 54 - .../src/main/kotlin/kotlin/collections/Set.kt | 6 + .../main/kotlin/kotlin/collections/Sets.kt | 210 - .../kotlin/collections/SlidingWindow.kt | 210 - .../kotlin/kotlin/comparisons/Comparisons.kt | 395 +- .../experimental/ContinuationInterceptor.kt | 40 - .../experimental/CoroutineContext.kt | 66 - .../coroutines/experimental/Coroutines.kt | 47 - .../experimental/CoroutinesLibrary.kt | 103 - .../experimental/EmptyCoroutineContext.kt | 128 - .../{intrinsics => }/Intrinsics.kt | 34 +- .../experimental/SafeContinuation.kt | 73 + .../experimental/SequenceBuilder.kt | 186 - .../kotlin/kotlin/internal/Annotations.kt | 55 - runtime/src/main/kotlin/kotlin/io/Console.kt | 6 +- .../src/main/kotlin/kotlin/io/Serializable.kt | 20 + .../main/kotlin/kotlin/jvm/JvmAnnotations.kt | 30 + runtime/src/main/kotlin/kotlin/math/math.kt | 231 +- .../kotlin/kotlin/properties/Delegates.kt | 71 - .../kotlin/kotlin/properties/Interfaces.kt | 65 - .../kotlin/properties/ObservableProperty.kt | 54 - .../src/main/kotlin/kotlin/ranges/Ranges.kt | 481 - .../src/main/kotlin/kotlin/ranges/_Ranges.kt | 465 - .../main/kotlin/kotlin/sequences/Sequence.kt | 39 - .../main/kotlin/kotlin/sequences/Sequences.kt | 2148 +-- .../src/main/kotlin/kotlin/text/Appendable.kt | 44 +- runtime/src/main/kotlin/kotlin/text/Char.kt | 14 +- runtime/src/main/kotlin/kotlin/text/Indent.kt | 124 - .../main/kotlin/kotlin/text/MatchResult.kt | 127 - runtime/src/main/kotlin/kotlin/text/Regex.kt | 42 +- .../main/kotlin/kotlin/text/StringBuilder.kt | 103 +- .../kotlin/text/StringNumberConversions.kt | 193 +- .../src/main/kotlin/kotlin/text/Strings.kt | 2555 +-- .../main/kotlin/kotlin/text/regex/Lexer.kt | 2 +- .../src/main/kotlin/kotlin/util/Lateinit.kt | 19 - .../main/kotlin/kotlin/util/Preconditions.kt | 114 - .../src/main/kotlin/kotlin/util/Standard.kt | 87 - runtime/src/main/kotlin/kotlin/util/Tuples.kt | 88 - .../csvparser/src/main/kotlin/CsvParser.kt | 2 +- 72 files changed, 2042 insertions(+), 27364 deletions(-) delete mode 100644 runtime/src/main/kotlin/konan/internal/Char.kt rename runtime/src/main/kotlin/kotlin/{collections/IndexedValue.kt => Comparator.kt} (58%) delete mode 100644 runtime/src/main/kotlin/kotlin/KotlinVersion.kt delete mode 100644 runtime/src/main/kotlin/kotlin/collections/AbstractIterator.kt rename runtime/src/main/kotlin/kotlin/collections/{AbstractCollection.kt => AbstractMutableCollection.kt} (68%) rename runtime/src/main/kotlin/kotlin/collections/{AbstractList.kt => AbstractMutableList.kt} (52%) delete mode 100644 runtime/src/main/kotlin/kotlin/collections/AbstractSet.kt delete mode 100644 runtime/src/main/kotlin/kotlin/collections/Grouping.kt delete mode 100644 runtime/src/main/kotlin/kotlin/collections/Iterables.kt delete mode 100644 runtime/src/main/kotlin/kotlin/collections/MapAccessors.kt delete mode 100644 runtime/src/main/kotlin/kotlin/collections/MapWithDefault.kt delete mode 100644 runtime/src/main/kotlin/kotlin/collections/ReversedViews.kt delete mode 100644 runtime/src/main/kotlin/kotlin/collections/Sets.kt delete mode 100644 runtime/src/main/kotlin/kotlin/collections/SlidingWindow.kt delete mode 100644 runtime/src/main/kotlin/kotlin/coroutines/experimental/ContinuationInterceptor.kt delete mode 100644 runtime/src/main/kotlin/kotlin/coroutines/experimental/CoroutineContext.kt delete mode 100644 runtime/src/main/kotlin/kotlin/coroutines/experimental/Coroutines.kt delete mode 100644 runtime/src/main/kotlin/kotlin/coroutines/experimental/CoroutinesLibrary.kt delete mode 100644 runtime/src/main/kotlin/kotlin/coroutines/experimental/EmptyCoroutineContext.kt rename runtime/src/main/kotlin/kotlin/coroutines/experimental/{intrinsics => }/Intrinsics.kt (71%) create mode 100644 runtime/src/main/kotlin/kotlin/coroutines/experimental/SafeContinuation.kt delete mode 100644 runtime/src/main/kotlin/kotlin/coroutines/experimental/SequenceBuilder.kt create mode 100644 runtime/src/main/kotlin/kotlin/io/Serializable.kt create mode 100644 runtime/src/main/kotlin/kotlin/jvm/JvmAnnotations.kt delete mode 100644 runtime/src/main/kotlin/kotlin/properties/Delegates.kt delete mode 100644 runtime/src/main/kotlin/kotlin/properties/Interfaces.kt delete mode 100644 runtime/src/main/kotlin/kotlin/properties/ObservableProperty.kt delete mode 100644 runtime/src/main/kotlin/kotlin/ranges/_Ranges.kt delete mode 100644 runtime/src/main/kotlin/kotlin/sequences/Sequence.kt delete mode 100644 runtime/src/main/kotlin/kotlin/text/Indent.kt delete mode 100644 runtime/src/main/kotlin/kotlin/text/MatchResult.kt delete mode 100644 runtime/src/main/kotlin/kotlin/util/Lateinit.kt delete mode 100644 runtime/src/main/kotlin/kotlin/util/Preconditions.kt delete mode 100644 runtime/src/main/kotlin/kotlin/util/Standard.kt delete mode 100644 runtime/src/main/kotlin/kotlin/util/Tuples.kt diff --git a/backend.native/build.gradle b/backend.native/build.gradle index 7da840f1b9a..9a9d10abb94 100644 --- a/backend.native/build.gradle +++ b/backend.native/build.gradle @@ -182,6 +182,9 @@ targetList.each { target -> args = [*konanArgs, '-output', project(':runtime').file("build/${target}Stdlib"), '-produce', 'library', '-module_name', 'stdlib', + '-Xmulti-platform', '-Xuse-experimental=kotlin.Experimental', + rootProject.file('libraries/generated'), + rootProject.file('libraries'), project(':Interop:Runtime').file('src/main/kotlin'), project(':Interop:Runtime').file('src/native/kotlin'), project(':Interop:JsRuntime').file('src/main/kotlin'), @@ -190,6 +193,8 @@ targetList.each { target -> inputs.dir(project(':Interop:Runtime').file('src/main/kotlin')) inputs.dir(project(':Interop:Runtime').file('src/native/kotlin')) inputs.dir(project(':Interop:JsRuntime').file('src/main/kotlin')) + inputs.dir(rootProject.file('libraries/generated')) + inputs.dir(rootProject.file('libraries/kotlin')) outputs.dir(project(':runtime').file("build/${target}Stdlib")) dependsOn ":runtime:${target}Runtime" diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index 717b2c98f2c..64893a7e2e2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -219,8 +219,20 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym val getProgressionLast = context.getInternalFunctions("getProgressionLast") .map { Pair(it.returnType, symbolTable.referenceSimpleFunction(it)) }.toMap() - val arrayContentToString = arrayTypes.associateBy({ it }, { arrayExtensionFun(it, "contentToString") }) - val arrayContentHashCode = arrayTypes.associateBy({ it }, { arrayExtensionFun(it, "contentHashCode") }) + val arrayContentToString = arrayTypes.associateBy({ it }, { findArrayExtension(it, "contentToString") }) + val arrayContentHashCode = arrayTypes.associateBy({ it }, { findArrayExtension(it, "contentHashCode") }) + + fun findArrayExtension(type: KotlinType, name: String): IrSimpleFunctionSymbol { + val descriptor = builtInsPackage("kotlin", "collections") + .getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND) + .singleOrNull { + it.valueParameters.isEmpty() + && (it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.defaultType == type + && it.isActual + } + ?: throw Error(type.toString()) + return symbolTable.referenceSimpleFunction(descriptor) + } override val copyRangeTo = arrays.map { symbol -> val packageViewDescriptor = builtIns.builtInsModule.getPackage(KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt index f3ee741c15b..3bb1a066dfc 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/LateinitLowering.kt @@ -51,7 +51,9 @@ internal class LateinitLowering( private val kotlinPackageScope = context.ir.irModule.descriptor.getPackage(KOTLIN_FQ_NAME).memberScope private val isInitializedPropertyDescriptor = kotlinPackageScope .getContributedVariables(Name.identifier("isInitialized"), NoLookupLocation.FROM_BACKEND).single { - it.extensionReceiverParameter.let { it != null && TypeUtils.getClassDescriptor(it.type) == context.reflectionTypes.kProperty0 } + it.extensionReceiverParameter.let { + it != null && TypeUtils.getClassDescriptor(it.type) == context.reflectionTypes.kProperty0 + } && it.isActual } private val isInitializedGetterDescriptor = isInitializedPropertyDescriptor.getter!! diff --git a/backend.native/tests/runtime/text/string_builder0.kt b/backend.native/tests/runtime/text/string_builder0.kt index 5c62698254d..4a5f60ae3a3 100644 --- a/backend.native/tests/runtime/text/string_builder0.kt +++ b/backend.native/tests/runtime/text/string_builder0.kt @@ -170,10 +170,10 @@ fun testReverse() { assertTrue(builder === builder.reverse()) assertEquals(builder, "654321") - builder.length = 1 + builder.setLength(1) assertEquals(builder, "6") - builder.length = 0 + builder.setLength(0) assertEquals(builder, "") var str: String = "a" @@ -261,7 +261,7 @@ fun testBasic() { assertEquals(19, sb.length) assertEquals("1, true12345678null", sb.toString()) - sb.length = 0 + sb.setLength(0) assertEquals(0, sb.length) assertEquals("", sb.toString()) } diff --git a/backend.native/tests/stdlib_external/text/harmony_regex/PatternTest2.kt b/backend.native/tests/stdlib_external/text/harmony_regex/PatternTest2.kt index 53ea11d1019..2658b676eb6 100644 --- a/backend.native/tests/stdlib_external/text/harmony_regex/PatternTest2.kt +++ b/backend.native/tests/stdlib_external/text/harmony_regex/PatternTest2.kt @@ -965,7 +965,7 @@ class PatternTest2 { assertEquals(4, result!!.range.start) // modify text - text.length = 0 + text.setLength(0) text.append("Text have been changed.") assertNull(regex.find(text)) diff --git a/runtime/src/main/kotlin/konan/concurrent.kt b/runtime/src/main/kotlin/konan/concurrent.kt index f5cb1b9ecfc..07ab529ba52 100644 --- a/runtime/src/main/kotlin/konan/concurrent.kt +++ b/runtime/src/main/kotlin/konan/concurrent.kt @@ -28,4 +28,4 @@ public annotation class Volatile public annotation class Synchronized @kotlin.internal.InlineOnly -public inline fun synchronized(@Suppress("UNUSED_PARAMETER") lock: Any, crossinline block: () -> R): R = block() \ No newline at end of file +public actual inline fun synchronized(@Suppress("UNUSED_PARAMETER") lock: Any, block: () -> R): R = block() \ No newline at end of file diff --git a/runtime/src/main/kotlin/konan/internal/Char.kt b/runtime/src/main/kotlin/konan/internal/Char.kt deleted file mode 100644 index c9e01f25d1e..00000000000 --- a/runtime/src/main/kotlin/konan/internal/Char.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.text - -/** - * Concatenates this Char and a String. - */ -@kotlin.internal.InlineOnly -public inline operator fun Char.plus(other: String) : String = this.toString() + other - -/** - * Returns `true` if this character is equal to the [other] character, optionally ignoring character case. - * - * @param ignoreCase `true` to ignore character case when comparing characters. By default `false`. - * - * Two characters are considered the same ignoring case if at least one of the following is `true`: - * - The two characters are the same (as compared by the == operator) - * - Applying the method [toUpperCase] to each character produces the same result - * - Applying the method [toLowerCase] to each character produces the same result - */ -public fun Char.equals(other: Char, ignoreCase: Boolean = false): Boolean { - @Suppress("DEPRECATED_IDENTITY_EQUALS") - if (this === other) return true - if (!ignoreCase) return false - - @Suppress("DEPRECATED_IDENTITY_EQUALS") - if (this.toUpperCase() === other.toUpperCase()) return true - @Suppress("DEPRECATED_IDENTITY_EQUALS") - if (this.toLowerCase() === other.toLowerCase()) return true - return false -} - -/** - * Returns `true` if this character is a Unicode surrogate code unit. - */ -public fun Char.isSurrogate(): Boolean = this in Char.MIN_SURROGATE..Char.MAX_SURROGATE diff --git a/runtime/src/main/kotlin/konan/internal/Coroutines.kt b/runtime/src/main/kotlin/konan/internal/Coroutines.kt index dff7a50c4c9..6ffb8e664c1 100644 --- a/runtime/src/main/kotlin/konan/internal/Coroutines.kt +++ b/runtime/src/main/kotlin/konan/internal/Coroutines.kt @@ -27,59 +27,6 @@ internal external fun getContinuation(): Continuation @PublishedApi internal external suspend fun returnIfSuspended(@Suppress("UNUSED_PARAMETER") argument: Any?): T -// Single-threaded continuation. -class SafeContinuation -constructor( - private val delegate: Continuation, - initialResult: Any? -) : Continuation { - - constructor(delegate: Continuation) : this(delegate, UNDECIDED) - - public override val context: CoroutineContext - get() = delegate.context - - private var result: Any? = initialResult - - companion object { - private val UNDECIDED: Any? = Any() - private val RESUMED: Any? = Any() - } - - private class Fail(val exception: Throwable) - - override fun resume(value: T) { - when { - result === UNDECIDED -> result = value - result === COROUTINE_SUSPENDED -> { - result = RESUMED - delegate.resume(value) - } - else -> throw IllegalStateException("Already resumed") - } - } - - override fun resumeWithException(exception: Throwable) { - when { - result === UNDECIDED -> result = Fail(exception) - result === COROUTINE_SUSPENDED -> { - result = RESUMED - delegate.resumeWithException(exception) - } - else -> throw IllegalStateException("Already resumed") - } - } - - fun getResult(): Any? { - if (this.result === UNDECIDED) this.result = COROUTINE_SUSPENDED - val result = this.result - when { - result === RESUMED -> return COROUTINE_SUSPENDED // already called continuation, indicate COROUTINE_SUSPENDED upstream - result is Fail -> throw result.exception - else -> return result // either COROUTINE_SUSPENDED or data - } - } -} @ExportForCompiler internal fun interceptContinuationIfNeeded( diff --git a/runtime/src/main/kotlin/konan/internal/Strings.kt b/runtime/src/main/kotlin/konan/internal/Strings.kt index af066726ae1..b96b64a140c 100644 --- a/runtime/src/main/kotlin/konan/internal/Strings.kt +++ b/runtime/src/main/kotlin/konan/internal/Strings.kt @@ -20,32 +20,32 @@ package kotlin.text * Returns the index within this string of the first occurrence of the specified character, starting from the specified offset. */ @SymbolName("Kotlin_String_indexOfChar") -external internal fun String.nativeIndexOf(ch: Char, fromIndex: Int): Int +external internal actual inline fun String.nativeIndexOf(ch: Char, fromIndex: Int): Int /** * Returns the index within this string of the first occurrence of the specified substring, starting from the specified offset. */ @SymbolName("Kotlin_String_indexOfString") -external internal fun String.nativeIndexOf(str: String, fromIndex: Int): Int +external internal actual fun String.nativeIndexOf(str: String, fromIndex: Int): Int /** * Returns the index within this string of the last occurrence of the specified character. */ @SymbolName("Kotlin_String_lastIndexOfChar") -external internal fun String.nativeLastIndexOf(ch: Char, fromIndex: Int): Int +external internal actual inline fun String.nativeLastIndexOf(ch: Char, fromIndex: Int): Int /** * Returns the index within this string of the last occurrence of the specified character, starting from the specified offset. */ @SymbolName("Kotlin_String_lastIndexOfString") -external internal fun String.nativeLastIndexOf(str: String, fromIndex: Int): Int +external internal actual fun String.nativeLastIndexOf(str: String, fromIndex: Int): Int /** * Returns `true` if this string is equal to [other], optionally ignoring character case. * * @param ignoreCase `true` to ignore character case when comparing strings. By default `false`. */ -public fun String?.equals(other: String?, ignoreCase: Boolean = false): Boolean { +public actual fun String?.equals(other: String?, ignoreCase: Boolean): Boolean { if (this === null) return other === null if (other === null) @@ -63,21 +63,21 @@ external internal fun stringEqualsIgnoreCase(thiz: String, other: String): Boole * Returns a new string with all occurrences of [oldChar] replaced with [newChar]. */ @SymbolName("Kotlin_String_replace") -external public fun String.replace( - oldChar: Char, newChar: Char, ignoreCase: Boolean = false): String +external public actual fun String.replace( + oldChar: Char, newChar: Char, ignoreCase: Boolean): String /** * Returns a new string obtained by replacing all occurrences of the [oldValue] substring in this string * with the specified [newValue] string. */ -public fun String.replace(oldValue: String, newValue: String, ignoreCase: Boolean = false): String = +public actual fun String.replace(oldValue: String, newValue: String, ignoreCase: Boolean): String = splitToSequence(oldValue, ignoreCase = ignoreCase).joinToString(separator = newValue) /** * Returns a new string with the first occurrence of [oldChar] replaced with [newChar]. */ -public fun String.replaceFirst(oldChar: Char, newChar: Char, ignoreCase: Boolean = false): String { +public actual fun String.replaceFirst(oldChar: Char, newChar: Char, ignoreCase: Boolean): String { val index = indexOf(oldChar, ignoreCase = ignoreCase) return if (index < 0) this else this.replaceRange(index, index + 1, newChar.toString()) } @@ -86,7 +86,7 @@ public fun String.replaceFirst(oldChar: Char, newChar: Char, ignoreCase: Boolean * Returns a new string obtained by replacing the first occurrence of the [oldValue] substring in this string * with the specified [newValue] string. */ -public fun String.replaceFirst(oldValue: String, newValue: String, ignoreCase: Boolean = false): String { +public actual fun String.replaceFirst(oldValue: String, newValue: String, ignoreCase: Boolean): String { val index = indexOf(oldValue, ignoreCase = ignoreCase) return if (index < 0) this else this.replaceRange(index, index + oldValue.length, newValue) } @@ -97,14 +97,14 @@ public fun String.replaceFirst(oldValue: String, newValue: String, ignoreCase: B * * @sample samples.text.Strings.decaptialize */ -public fun String.decapitalize(): String { +public actual fun String.decapitalize(): String { return if (isNotEmpty() && this[0].isUpperCase()) substring(0, 1).toLowerCase() + substring(1) else this } /** * Returns `true` if this string is empty or consists solely of whitespace characters. */ -public fun CharSequence.isBlank(): Boolean = length == 0 || indices.all { this[it].isWhitespace() } +public actual fun CharSequence.isBlank(): Boolean = length == 0 || indices.all { this[it].isWhitespace() } /** * Returns the substring of this string starting at the [startIndex] and ending right before the [endIndex]. @@ -113,9 +113,18 @@ public fun CharSequence.isBlank(): Boolean = length == 0 || indices.all { this[i * @param endIndex the end index (exclusive). */ @kotlin.internal.InlineOnly -public inline fun String.substring(startIndex: Int, endIndex: Int): String = +public actual inline fun String.substring(startIndex: Int, endIndex: Int): String = subSequence(startIndex, endIndex) as String +/** + * Returns the substring of this string starting at the [startIndex]. + * + * @param startIndex the start index (inclusive). + */ +@kotlin.internal.InlineOnly +public actual inline fun String.substring(startIndex: Int): String = + subSequence(startIndex, this.length) as String + /** * Returns `true` if this string starts with the specified prefix. */ @@ -142,9 +151,9 @@ public fun String.endsWith(suffix: String, ignoreCase: Boolean = false): Boolean * @param length the length of the substring to compare. */ @SymbolName("Kotlin_CharSequence_regionMatches") -external public fun CharSequence.regionMatches( +external public actual fun CharSequence.regionMatches( thisOffset: Int, other: CharSequence, otherOffset: Int, length: Int, - ignoreCase: Boolean = false): Boolean + ignoreCase: Boolean): Boolean /** @@ -163,14 +172,14 @@ external public fun String.regionMatches( * Returns a copy of this string converted to upper case using the rules of the default locale. */ @SymbolName("Kotlin_String_toUpperCase") -external public fun String.toUpperCase(): String +external public actual fun String.toUpperCase(): String /** * Returns a copy of this string converted to lower case using the rules of the default locale. */ @SymbolName("Kotlin_String_toLowerCase") @Suppress("NOTHING_TO_INLINE") -external public inline fun String.toLowerCase(): String +external public actual inline fun String.toLowerCase(): String /** * Returns an array containing all characters of the specified string. @@ -184,6 +193,6 @@ external public fun String.toCharArray() : CharArray * * @sample samples.text.Strings.captialize */ -public fun String.capitalize(): String { +public actual fun String.capitalize(): String { return if (isNotEmpty() && this[0].isLowerCase()) substring(0, 1).toUpperCase() + substring(1) else this } \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/Arrays.kt b/runtime/src/main/kotlin/kotlin/Arrays.kt index 168705f9c80..c253cb13a4c 100644 --- a/runtime/src/main/kotlin/kotlin/Arrays.kt +++ b/runtime/src/main/kotlin/kotlin/Arrays.kt @@ -429,12238 +429,6 @@ private class BooleanIteratorImpl(val collection: BooleanArray) : BooleanIterato } } -// From ArraysJVM.kt -/** Returns the array if it's not `null`, or an empty array otherwise. */ -public inline fun Array?.orEmpty(): Array = this ?: emptyArray() - -// This part is from generated _Arrays.kt. - - -/** - * Returns 1st *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun Array.component1(): T { - return get(0) -} - -/** - * Returns 1st *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun ByteArray.component1(): Byte { - return get(0) -} - -/** - * Returns 1st *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun ShortArray.component1(): Short { - return get(0) -} - -/** - * Returns 1st *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun IntArray.component1(): Int { - return get(0) -} - -/** - * Returns 1st *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun LongArray.component1(): Long { - return get(0) -} - -/** - * Returns 1st *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun FloatArray.component1(): Float { - return get(0) -} - -/** - * Returns 1st *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun DoubleArray.component1(): Double { - return get(0) -} - -/** - * Returns 1st *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun BooleanArray.component1(): Boolean { - return get(0) -} - -/** - * Returns 1st *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun CharArray.component1(): Char { - return get(0) -} - -/** - * Returns 2nd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun Array.component2(): T { - return get(1) -} - -/** - * Returns 2nd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun ByteArray.component2(): Byte { - return get(1) -} - -/** - * Returns 2nd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun ShortArray.component2(): Short { - return get(1) -} - -/** - * Returns 2nd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun IntArray.component2(): Int { - return get(1) -} - -/** - * Returns 2nd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun LongArray.component2(): Long { - return get(1) -} - -/** - * Returns 2nd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun FloatArray.component2(): Float { - return get(1) -} - -/** - * Returns 2nd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun DoubleArray.component2(): Double { - return get(1) -} - -/** - * Returns 2nd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun BooleanArray.component2(): Boolean { - return get(1) -} - -/** - * Returns 2nd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun CharArray.component2(): Char { - return get(1) -} - -/** - * Returns 3rd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun Array.component3(): T { - return get(2) -} - -/** - * Returns 3rd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun ByteArray.component3(): Byte { - return get(2) -} - -/** - * Returns 3rd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun ShortArray.component3(): Short { - return get(2) -} - -/** - * Returns 3rd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun IntArray.component3(): Int { - return get(2) -} - -/** - * Returns 3rd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun LongArray.component3(): Long { - return get(2) -} - -/** - * Returns 3rd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun FloatArray.component3(): Float { - return get(2) -} - -/** - * Returns 3rd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun DoubleArray.component3(): Double { - return get(2) -} - -/** - * Returns 3rd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun BooleanArray.component3(): Boolean { - return get(2) -} - -/** - * Returns 3rd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun CharArray.component3(): Char { - return get(2) -} - -/** - * Returns 4th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun Array.component4(): T { - return get(3) -} - -/** - * Returns 4th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun ByteArray.component4(): Byte { - return get(3) -} - -/** - * Returns 4th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun ShortArray.component4(): Short { - return get(3) -} - -/** - * Returns 4th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun IntArray.component4(): Int { - return get(3) -} - -/** - * Returns 4th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun LongArray.component4(): Long { - return get(3) -} - -/** - * Returns 4th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun FloatArray.component4(): Float { - return get(3) -} - -/** - * Returns 4th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun DoubleArray.component4(): Double { - return get(3) -} - -/** - * Returns 4th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun BooleanArray.component4(): Boolean { - return get(3) -} - -/** - * Returns 4th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun CharArray.component4(): Char { - return get(3) -} - -/** - * Returns 5th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun Array.component5(): T { - return get(4) -} - -/** - * Returns 5th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun ByteArray.component5(): Byte { - return get(4) -} - -/** - * Returns 5th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun ShortArray.component5(): Short { - return get(4) -} - -/** - * Returns 5th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun IntArray.component5(): Int { - return get(4) -} - -/** - * Returns 5th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun LongArray.component5(): Long { - return get(4) -} - -/** - * Returns 5th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun FloatArray.component5(): Float { - return get(4) -} - -/** - * Returns 5th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun DoubleArray.component5(): Double { - return get(4) -} - -/** - * Returns 5th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun BooleanArray.component5(): Boolean { - return get(4) -} - -/** - * Returns 5th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun CharArray.component5(): Char { - return get(4) -} - -/** - * Returns `true` if all elements match the given [predicate]. - */ -public inline fun Array.all(predicate: (T) -> Boolean): Boolean { - for (element in this) if (!predicate(element)) return false - return true -} - -/** - * Returns `true` if all elements match the given [predicate]. - */ -public inline fun ByteArray.all(predicate: (Byte) -> Boolean): Boolean { - for (element in this) if (!predicate(element)) return false - return true -} - -/** - * Returns `true` if all elements match the given [predicate]. - */ -public inline fun ShortArray.all(predicate: (Short) -> Boolean): Boolean { - for (element in this) if (!predicate(element)) return false - return true -} - -/** - * Returns `true` if all elements match the given [predicate]. - */ -public inline fun IntArray.all(predicate: (Int) -> Boolean): Boolean { - for (element in this) if (!predicate(element)) return false - return true -} - -/** - * Returns `true` if all elements match the given [predicate]. - */ -public inline fun LongArray.all(predicate: (Long) -> Boolean): Boolean { - for (element in this) if (!predicate(element)) return false - return true -} - -/** - * Returns `true` if all elements match the given [predicate]. - */ -public inline fun FloatArray.all(predicate: (Float) -> Boolean): Boolean { - for (element in this) if (!predicate(element)) return false - return true -} - -/** - * Returns `true` if all elements match the given [predicate]. - */ -public inline fun DoubleArray.all(predicate: (Double) -> Boolean): Boolean { - for (element in this) if (!predicate(element)) return false - return true -} - -/** - * Returns `true` if all elements match the given [predicate]. - */ -public inline fun BooleanArray.all(predicate: (Boolean) -> Boolean): Boolean { - for (element in this) if (!predicate(element)) return false - return true -} - -/** - * Returns `true` if all elements match the given [predicate]. - */ -public inline fun CharArray.all(predicate: (Char) -> Boolean): Boolean { - for (element in this) if (!predicate(element)) return false - return true -} - -/** - * Returns `true` if array has at least one element. - */ -public fun Array.any(): Boolean { - for (element in this) return true - return false -} - -/** - * Returns `true` if array has at least one element. - */ -public fun ByteArray.any(): Boolean { - for (element in this) return true - return false -} - -/** - * Returns `true` if array has at least one element. - */ -public fun ShortArray.any(): Boolean { - for (element in this) return true - return false -} - -/** - * Returns `true` if array has at least one element. - */ -public fun IntArray.any(): Boolean { - for (element in this) return true - return false -} - -/** - * Returns `true` if array has at least one element. - */ -public fun LongArray.any(): Boolean { - for (element in this) return true - return false -} - -/** - * Returns `true` if array has at least one element. - */ -public fun FloatArray.any(): Boolean { - for (element in this) return true - return false -} - -/** - * Returns `true` if array has at least one element. - */ -public fun DoubleArray.any(): Boolean { - for (element in this) return true - return false -} - -/** - * Returns `true` if array has at least one element. - */ -public fun BooleanArray.any(): Boolean { - for (element in this) return true - return false -} - -/** - * Returns `true` if array has at least one element. - */ -public fun CharArray.any(): Boolean { - for (element in this) return true - return false -} - -/** - * Returns `true` if at least one element matches the given [predicate]. - */ -public inline fun Array.any(predicate: (T) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return true - return false -} - -/** - * Returns `true` if at least one element matches the given [predicate]. - */ -public inline fun ByteArray.any(predicate: (Byte) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return true - return false -} - -/** - * Returns `true` if at least one element matches the given [predicate]. - */ -public inline fun ShortArray.any(predicate: (Short) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return true - return false -} - -/** - * Returns `true` if at least one element matches the given [predicate]. - */ -public inline fun IntArray.any(predicate: (Int) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return true - return false -} - -/** - * Returns `true` if at least one element matches the given [predicate]. - */ -public inline fun LongArray.any(predicate: (Long) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return true - return false -} - -/** - * Returns `true` if at least one element matches the given [predicate]. - */ -public inline fun FloatArray.any(predicate: (Float) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return true - return false -} - -/** - * Returns `true` if at least one element matches the given [predicate]. - */ -public inline fun DoubleArray.any(predicate: (Double) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return true - return false -} - -/** - * Returns `true` if at least one element matches the given [predicate]. - */ -public inline fun BooleanArray.any(predicate: (Boolean) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return true - return false -} - -/** - * Returns `true` if at least one element matches the given [predicate]. - */ -public inline fun CharArray.any(predicate: (Char) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return true - return false -} - -/** - * Returns `true` if [element] is found in the array. - */ -public operator fun <@kotlin.internal.OnlyInputTypes T> Array.contains(element: T): Boolean { - return indexOf(element) >= 0 -} - -/** - * Returns `true` if [element] is found in the array. - */ -public operator fun ByteArray.contains(element: Byte): Boolean { - return indexOf(element) >= 0 -} - -/** - * Returns `true` if [element] is found in the array. - */ -public operator fun ShortArray.contains(element: Short): Boolean { - return indexOf(element) >= 0 -} - -/** - * Returns `true` if [element] is found in the array. - */ -public operator fun IntArray.contains(element: Int): Boolean { - return indexOf(element) >= 0 -} - -/** - * Returns `true` if [element] is found in the array. - */ -public operator fun LongArray.contains(element: Long): Boolean { - return indexOf(element) >= 0 -} - -/** - * Returns `true` if [element] is found in the array. - */ -public operator fun FloatArray.contains(element: Float): Boolean { - return indexOf(element) >= 0 -} - -/** - * Returns `true` if [element] is found in the array. - */ -public operator fun DoubleArray.contains(element: Double): Boolean { - return indexOf(element) >= 0 -} - -/** - * Returns `true` if [element] is found in the array. - */ -public operator fun BooleanArray.contains(element: Boolean): Boolean { - return indexOf(element) >= 0 -} - -/** - * Returns `true` if [element] is found in the array. - */ -public operator fun CharArray.contains(element: Char): Boolean { - return indexOf(element) >= 0 -} - -/** - * Returns the number of elements in this array. - */ -@kotlin.internal.InlineOnly -public inline fun Array.count(): Int = this.size - -/** - * Returns the number of elements in this array. - */ -@kotlin.internal.InlineOnly -public inline fun ByteArray.count(): Int { - return size -} - -/** - * Returns the number of elements in this array. - */ -@kotlin.internal.InlineOnly -public inline fun ShortArray.count(): Int { - return size -} - -/** - * Returns the number of elements in this array. - */ -@kotlin.internal.InlineOnly -public inline fun IntArray.count(): Int { - return size -} - -/** - * Returns the number of elements in this array. - */ -@kotlin.internal.InlineOnly -public inline fun LongArray.count(): Int { - return size -} - -/** - * Returns the number of elements in this array. - */ -@kotlin.internal.InlineOnly -public inline fun FloatArray.count(): Int { - return size -} - -/** - * Returns the number of elements in this array. - */ -@kotlin.internal.InlineOnly -public inline fun DoubleArray.count(): Int { - return size -} - -/** - * Returns the number of elements in this array. - */ -@kotlin.internal.InlineOnly -public inline fun BooleanArray.count(): Int { - return size -} - -/** - * Returns the number of elements in this array. - */ -@kotlin.internal.InlineOnly -public inline fun CharArray.count(): Int { - return size -} - -/** - * Returns the number of elements matching the given [predicate]. - */ -public inline fun Array.count(predicate: (T) -> Boolean): Int { - var count = 0 - for (element in this) if (predicate(element)) count++ - return count -} - -/** - * Returns the number of elements matching the given [predicate]. - */ -public inline fun ByteArray.count(predicate: (Byte) -> Boolean): Int { - var count = 0 - for (element in this) if (predicate(element)) count++ - return count -} - -/** - * Returns the number of elements matching the given [predicate]. - */ -public inline fun ShortArray.count(predicate: (Short) -> Boolean): Int { - var count = 0 - for (element in this) if (predicate(element)) count++ - return count -} - -/** - * Returns the number of elements matching the given [predicate]. - */ -public inline fun IntArray.count(predicate: (Int) -> Boolean): Int { - var count = 0 - for (element in this) if (predicate(element)) count++ - return count -} - -/** - * Returns the number of elements matching the given [predicate]. - */ -public inline fun LongArray.count(predicate: (Long) -> Boolean): Int { - var count = 0 - for (element in this) if (predicate(element)) count++ - return count -} - -/** - * Returns the number of elements matching the given [predicate]. - */ -public inline fun FloatArray.count(predicate: (Float) -> Boolean): Int { - var count = 0 - for (element in this) if (predicate(element)) count++ - return count -} - -/** - * Returns the number of elements matching the given [predicate]. - */ -public inline fun DoubleArray.count(predicate: (Double) -> Boolean): Int { - var count = 0 - for (element in this) if (predicate(element)) count++ - return count -} - -/** - * Returns the number of elements matching the given [predicate]. - */ -public inline fun BooleanArray.count(predicate: (Boolean) -> Boolean): Int { - var count = 0 - for (element in this) if (predicate(element)) count++ - return count -} - -/** - * Returns the number of elements matching the given [predicate]. - */ -public inline fun CharArray.count(predicate: (Char) -> Boolean): Int { - var count = 0 - for (element in this) if (predicate(element)) count++ - return count -} - -/** - * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun Array.elementAt(index: Int): T { - return get(index) -} - -/** - * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun ByteArray.elementAt(index: Int): Byte { - return get(index) -} - -/** - * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun ShortArray.elementAt(index: Int): Short { - return get(index) -} - -/** - * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun IntArray.elementAt(index: Int): Int { - return get(index) -} - -/** - * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun LongArray.elementAt(index: Int): Long { - return get(index) -} - -/** - * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun FloatArray.elementAt(index: Int): Float { - return get(index) -} - -/** - * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun DoubleArray.elementAt(index: Int): Double { - return get(index) -} - -/** - * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun BooleanArray.elementAt(index: Int): Boolean { - return get(index) -} - -/** - * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun CharArray.elementAt(index: Int): Char { - return get(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun Array.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun ByteArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Byte): Byte { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun ShortArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Short): Short { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun IntArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Int): Int { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun LongArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Long): Long { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun FloatArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Float): Float { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun DoubleArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Double): Double { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun BooleanArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Boolean): Boolean { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun CharArray.elementAtOrElse(index: Int, defaultValue: (Int) -> Char): Char { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun Array.elementAtOrNull(index: Int): T? { - return this.getOrNull(index) -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun ByteArray.elementAtOrNull(index: Int): Byte? { - return this.getOrNull(index) -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun ShortArray.elementAtOrNull(index: Int): Short? { - return this.getOrNull(index) -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun IntArray.elementAtOrNull(index: Int): Int? { - return this.getOrNull(index) -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun LongArray.elementAtOrNull(index: Int): Long? { - return this.getOrNull(index) -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun FloatArray.elementAtOrNull(index: Int): Float? { - return this.getOrNull(index) -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun DoubleArray.elementAtOrNull(index: Int): Double? { - return this.getOrNull(index) -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun BooleanArray.elementAtOrNull(index: Int): Boolean? { - return this.getOrNull(index) -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun CharArray.elementAtOrNull(index: Int): Char? { - return this.getOrNull(index) -} - -/** - * Returns first element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun Array.first(): T { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[0] -} - -/** - * Returns first element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun ByteArray.first(): Byte { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[0] -} - -/** - * Returns first element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun ShortArray.first(): Short { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[0] -} - -/** - * Returns first element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun IntArray.first(): Int { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[0] -} - -/** - * Returns first element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun LongArray.first(): Long { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[0] -} - -/** - * Returns first element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun FloatArray.first(): Float { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[0] -} - -/** - * Returns first element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun DoubleArray.first(): Double { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[0] -} - -/** - * Returns first element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun BooleanArray.first(): Boolean { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[0] -} - -/** - * Returns first element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun CharArray.first(): Char { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[0] -} - -/** - * Returns the first element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun Array.first(predicate: (T) -> Boolean): T { - for (element in this) if (predicate(element)) return element - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the first element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun ByteArray.first(predicate: (Byte) -> Boolean): Byte { - for (element in this) if (predicate(element)) return element - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the first element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun ShortArray.first(predicate: (Short) -> Boolean): Short { - for (element in this) if (predicate(element)) return element - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the first element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun IntArray.first(predicate: (Int) -> Boolean): Int { - for (element in this) if (predicate(element)) return element - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the first element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun LongArray.first(predicate: (Long) -> Boolean): Long { - for (element in this) if (predicate(element)) return element - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the first element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun FloatArray.first(predicate: (Float) -> Boolean): Float { - for (element in this) if (predicate(element)) return element - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the first element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun DoubleArray.first(predicate: (Double) -> Boolean): Double { - for (element in this) if (predicate(element)) return element - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the first element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun BooleanArray.first(predicate: (Boolean) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return element - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the first element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun CharArray.first(predicate: (Char) -> Boolean): Char { - for (element in this) if (predicate(element)) return element - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun Array.getOrElse(index: Int, defaultValue: (Int) -> T): T { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun ByteArray.getOrElse(index: Int, defaultValue: (Int) -> Byte): Byte { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun ShortArray.getOrElse(index: Int, defaultValue: (Int) -> Short): Short { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun IntArray.getOrElse(index: Int, defaultValue: (Int) -> Int): Int { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun LongArray.getOrElse(index: Int, defaultValue: (Int) -> Long): Long { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun FloatArray.getOrElse(index: Int, defaultValue: (Int) -> Float): Float { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun DoubleArray.getOrElse(index: Int, defaultValue: (Int) -> Double): Double { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun BooleanArray.getOrElse(index: Int, defaultValue: (Int) -> Boolean): Boolean { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this array. - */ -@kotlin.internal.InlineOnly -public inline fun CharArray.getOrElse(index: Int, defaultValue: (Int) -> Char): Char { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -public fun Array.getOrNull(index: Int): T? { - return if (index >= 0 && index <= lastIndex) get(index) else null -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -public fun ByteArray.getOrNull(index: Int): Byte? { - return if (index >= 0 && index <= lastIndex) get(index) else null -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -public fun ShortArray.getOrNull(index: Int): Short? { - return if (index >= 0 && index <= lastIndex) get(index) else null -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -public fun IntArray.getOrNull(index: Int): Int? { - return if (index >= 0 && index <= lastIndex) get(index) else null -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -public fun LongArray.getOrNull(index: Int): Long? { - return if (index >= 0 && index <= lastIndex) get(index) else null -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -public fun FloatArray.getOrNull(index: Int): Float? { - return if (index >= 0 && index <= lastIndex) get(index) else null -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -public fun DoubleArray.getOrNull(index: Int): Double? { - return if (index >= 0 && index <= lastIndex) get(index) else null -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -public fun BooleanArray.getOrNull(index: Int): Boolean? { - return if (index >= 0 && index <= lastIndex) get(index) else null -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this array. - */ -public fun CharArray.getOrNull(index: Int): Char? { - return if (index >= 0 && index <= lastIndex) get(index) else null -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun IntArray.fold(initial: R, operation: (acc: R, Int) -> R): R { - var accumulator = initial - for (element in this) accumulator = operation(accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun LongArray.fold(initial: R, operation: (acc: R, Long) -> R): R { - var accumulator = initial - for (element in this) accumulator = operation(accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun FloatArray.fold(initial: R, operation: (acc: R, Float) -> R): R { - var accumulator = initial - for (element in this) accumulator = operation(accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun DoubleArray.fold(initial: R, operation: (acc: R, Double) -> R): R { - var accumulator = initial - for (element in this) accumulator = operation(accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun BooleanArray.fold(initial: R, operation: (acc: R, Boolean) -> R): R { - var accumulator = initial - for (element in this) accumulator = operation(accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun CharArray.fold(initial: R, operation: (acc: R, Char) -> R): R { - var accumulator = initial - for (element in this) accumulator = operation(accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself, and calculates the next accumulator value. - */ -public inline fun Array.foldIndexed(initial: R, operation: (index: Int, acc: R, T) -> R): R { - var index = 0 - var accumulator = initial - for (element in this) accumulator = operation(index++, accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself, and calculates the next accumulator value. - */ -public inline fun ByteArray.foldIndexed(initial: R, operation: (index: Int, acc: R, Byte) -> R): R { - var index = 0 - var accumulator = initial - for (element in this) accumulator = operation(index++, accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself, and calculates the next accumulator value. - */ -public inline fun ShortArray.foldIndexed(initial: R, operation: (index: Int, acc: R, Short) -> R): R { - var index = 0 - var accumulator = initial - for (element in this) accumulator = operation(index++, accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself, and calculates the next accumulator value. - */ -public inline fun IntArray.foldIndexed(initial: R, operation: (index: Int, acc: R, Int) -> R): R { - var index = 0 - var accumulator = initial - for (element in this) accumulator = operation(index++, accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself, and calculates the next accumulator value. - */ -public inline fun LongArray.foldIndexed(initial: R, operation: (index: Int, acc: R, Long) -> R): R { - var index = 0 - var accumulator = initial - for (element in this) accumulator = operation(index++, accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself, and calculates the next accumulator value. - */ -public inline fun FloatArray.foldIndexed(initial: R, operation: (index: Int, acc: R, Float) -> R): R { - var index = 0 - var accumulator = initial - for (element in this) accumulator = operation(index++, accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself, and calculates the next accumulator value. - */ -public inline fun DoubleArray.foldIndexed(initial: R, operation: (index: Int, acc: R, Double) -> R): R { - var index = 0 - var accumulator = initial - for (element in this) accumulator = operation(index++, accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself, and calculates the next accumulator value. - */ -public inline fun BooleanArray.foldIndexed(initial: R, operation: (index: Int, acc: R, Boolean) -> R): R { - var index = 0 - var accumulator = initial - for (element in this) accumulator = operation(index++, accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself, and calculates the next accumulator value. - */ -public inline fun CharArray.foldIndexed(initial: R, operation: (index: Int, acc: R, Char) -> R): R { - var index = 0 - var accumulator = initial - for (element in this) accumulator = operation(index++, accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun Array.foldRight(initial: R, operation: (T, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun ByteArray.foldRight(initial: R, operation: (Byte, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun ShortArray.foldRight(initial: R, operation: (Short, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun IntArray.foldRight(initial: R, operation: (Int, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun LongArray.foldRight(initial: R, operation: (Long, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun FloatArray.foldRight(initial: R, operation: (Float, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun DoubleArray.foldRight(initial: R, operation: (Double, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun BooleanArray.foldRight(initial: R, operation: (Boolean, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun CharArray.foldRight(initial: R, operation: (Char, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun Array.foldRightIndexed(initial: R, operation: (index: Int, T, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun ByteArray.foldRightIndexed(initial: R, operation: (index: Int, Byte, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun ShortArray.foldRightIndexed(initial: R, operation: (index: Int, Short, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun IntArray.foldRightIndexed(initial: R, operation: (index: Int, Int, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun LongArray.foldRightIndexed(initial: R, operation: (index: Int, Long, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun FloatArray.foldRightIndexed(initial: R, operation: (index: Int, Float, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun DoubleArray.foldRightIndexed(initial: R, operation: (index: Int, Double, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun BooleanArray.foldRightIndexed(initial: R, operation: (index: Int, Boolean, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun CharArray.foldRightIndexed(initial: R, operation: (index: Int, Char, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Performs the given [action] on each element. - */ -public inline fun Array.forEach(action: (T) -> Unit): Unit { - for (element in this) action(element) -} - -/** - * Performs the given [action] on each element. - */ -public inline fun ByteArray.forEach(action: (Byte) -> Unit): Unit { - for (element in this) action(element) -} - -/** - * Performs the given [action] on each element. - */ -public inline fun ShortArray.forEach(action: (Short) -> Unit): Unit { - for (element in this) action(element) -} - -/** - * Performs the given [action] on each element. - */ -public inline fun IntArray.forEach(action: (Int) -> Unit): Unit { - for (element in this) action(element) -} - -/** - * Performs the given [action] on each element. - */ -public inline fun LongArray.forEach(action: (Long) -> Unit): Unit { - for (element in this) action(element) -} - -/** - * Performs the given [action] on each element. - */ -public inline fun FloatArray.forEach(action: (Float) -> Unit): Unit { - for (element in this) action(element) -} - -/** - * Performs the given [action] on each element. - */ -public inline fun DoubleArray.forEach(action: (Double) -> Unit): Unit { - for (element in this) action(element) -} - -/** - * Performs the given [action] on each element. - */ -public inline fun BooleanArray.forEach(action: (Boolean) -> Unit): Unit { - for (element in this) action(element) -} - -/** - * Performs the given [action] on each element. - */ -public inline fun CharArray.forEach(action: (Char) -> Unit): Unit { - for (element in this) action(element) -} - -/** - * Performs the given [action] on each element, providing sequential index with the element. - * @param [action] function that takes the index of an element and the element itself - * and performs the desired action on the element. - */ -public inline fun Array.forEachIndexed(action: (index: Int, T) -> Unit): Unit { - var index = 0 - for (item in this) action(index++, item) -} - -/** - * Performs the given [action] on each element, providing sequential index with the element. - * @param [action] function that takes the index of an element and the element itself - * and performs the desired action on the element. - */ -public inline fun ByteArray.forEachIndexed(action: (index: Int, Byte) -> Unit): Unit { - var index = 0 - for (item in this) action(index++, item) -} - -/** - * Performs the given [action] on each element, providing sequential index with the element. - * @param [action] function that takes the index of an element and the element itself - * and performs the desired action on the element. - */ -public inline fun ShortArray.forEachIndexed(action: (index: Int, Short) -> Unit): Unit { - var index = 0 - for (item in this) action(index++, item) -} - -/** - * Performs the given [action] on each element, providing sequential index with the element. - * @param [action] function that takes the index of an element and the element itself - * and performs the desired action on the element. - */ -public inline fun IntArray.forEachIndexed(action: (index: Int, Int) -> Unit): Unit { - var index = 0 - for (item in this) action(index++, item) -} - -/** - * Performs the given [action] on each element, providing sequential index with the element. - * @param [action] function that takes the index of an element and the element itself - * and performs the desired action on the element. - */ -public inline fun LongArray.forEachIndexed(action: (index: Int, Long) -> Unit): Unit { - var index = 0 - for (item in this) action(index++, item) -} - -/** - * Performs the given [action] on each element, providing sequential index with the element. - * @param [action] function that takes the index of an element and the element itself - * and performs the desired action on the element. - */ -public inline fun FloatArray.forEachIndexed(action: (index: Int, Float) -> Unit): Unit { - var index = 0 - for (item in this) action(index++, item) -} - -/** - * Performs the given [action] on each element, providing sequential index with the element. - * @param [action] function that takes the index of an element and the element itself - * and performs the desired action on the element. - */ -public inline fun DoubleArray.forEachIndexed(action: (index: Int, Double) -> Unit): Unit { - var index = 0 - for (item in this) action(index++, item) -} - -/** - * Performs the given [action] on each element, providing sequential index with the element. - * @param [action] function that takes the index of an element and the element itself - * and performs the desired action on the element. - */ -public inline fun BooleanArray.forEachIndexed(action: (index: Int, Boolean) -> Unit): Unit { - var index = 0 - for (item in this) action(index++, item) -} - -/** - * Performs the given [action] on each element, providing sequential index with the element. - * @param [action] function that takes the index of an element and the element itself - * and performs the desired action on the element. - */ -public inline fun CharArray.forEachIndexed(action: (index: Int, Char) -> Unit): Unit { - var index = 0 - for (item in this) action(index++, item) -} - -/** - * Returns the largest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -@SinceKotlin("1.1") -public fun Array.max(): Double? { - if (isEmpty()) return null - var max = this[0] - if (max.isNaN()) return max - for (i in 1..lastIndex) { - val e = this[i] - if (e.isNaN()) return e - if (max < e) max = e - } - return max -} - -/** - * Returns the largest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -@SinceKotlin("1.1") -public fun Array.max(): Float? { - if (isEmpty()) return null - var max = this[0] - if (max.isNaN()) return max - for (i in 1..lastIndex) { - val e = this[i] - if (e.isNaN()) return e - if (max < e) max = e - } - return max -} - -/** - * Returns the largest element or `null` if there are no elements. - */ -public fun > Array.max(): T? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (max < e) max = e - } - return max -} - -/** - * Returns the largest element or `null` if there are no elements. - */ -public fun ByteArray.max(): Byte? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (max < e) max = e - } - return max -} - -/** - * Returns the largest element or `null` if there are no elements. - */ -public fun ShortArray.max(): Short? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (max < e) max = e - } - return max -} - -/** - * Returns the largest element or `null` if there are no elements. - */ -public fun IntArray.max(): Int? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (max < e) max = e - } - return max -} - -/** - * Returns the largest element or `null` if there are no elements. - */ -public fun LongArray.max(): Long? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (max < e) max = e - } - return max -} - -/** - * Returns the largest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -public fun FloatArray.max(): Float? { - if (isEmpty()) return null - var max = this[0] - if (max.isNaN()) return max - for (i in 1..lastIndex) { - val e = this[i] - if (e.isNaN()) return e - if (max < e) max = e - } - return max -} - -/** - * Returns the largest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -public fun DoubleArray.max(): Double? { - if (isEmpty()) return null - var max = this[0] - if (max.isNaN()) return max - for (i in 1..lastIndex) { - val e = this[i] - if (e.isNaN()) return e - if (max < e) max = e - } - return max -} - -/** - * Returns the largest element or `null` if there are no elements. - */ -public fun CharArray.max(): Char? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (max < e) max = e - } - return max -} - -/** - * Returns the first element yielding the largest value of the given function or `null` if there are no elements. - */ -public inline fun > Array.maxBy(selector: (T) -> R): T? { - if (isEmpty()) return null - var maxElem = this[0] - var maxValue = selector(maxElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (maxValue < v) { - maxElem = e - maxValue = v - } - } - return maxElem -} - -/** - * Returns the first element yielding the largest value of the given function or `null` if there are no elements. - */ -public inline fun > ByteArray.maxBy(selector: (Byte) -> R): Byte? { - if (isEmpty()) return null - var maxElem = this[0] - var maxValue = selector(maxElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (maxValue < v) { - maxElem = e - maxValue = v - } - } - return maxElem -} - -/** - * Returns the first element yielding the largest value of the given function or `null` if there are no elements. - */ -public inline fun > ShortArray.maxBy(selector: (Short) -> R): Short? { - if (isEmpty()) return null - var maxElem = this[0] - var maxValue = selector(maxElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (maxValue < v) { - maxElem = e - maxValue = v - } - } - return maxElem -} - -/** - * Returns the first element yielding the largest value of the given function or `null` if there are no elements. - */ -public inline fun > IntArray.maxBy(selector: (Int) -> R): Int? { - if (isEmpty()) return null - var maxElem = this[0] - var maxValue = selector(maxElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (maxValue < v) { - maxElem = e - maxValue = v - } - } - return maxElem -} - -/** - * Returns the first element yielding the largest value of the given function or `null` if there are no elements. - */ -public inline fun > LongArray.maxBy(selector: (Long) -> R): Long? { - if (isEmpty()) return null - var maxElem = this[0] - var maxValue = selector(maxElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (maxValue < v) { - maxElem = e - maxValue = v - } - } - return maxElem -} - -/** - * Returns the first element yielding the largest value of the given function or `null` if there are no elements. - */ -public inline fun > FloatArray.maxBy(selector: (Float) -> R): Float? { - if (isEmpty()) return null - var maxElem = this[0] - var maxValue = selector(maxElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (maxValue < v) { - maxElem = e - maxValue = v - } - } - return maxElem -} - -/** - * Returns the first element yielding the largest value of the given function or `null` if there are no elements. - */ -public inline fun > DoubleArray.maxBy(selector: (Double) -> R): Double? { - if (isEmpty()) return null - var maxElem = this[0] - var maxValue = selector(maxElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (maxValue < v) { - maxElem = e - maxValue = v - } - } - return maxElem -} - -/** - * Returns the first element yielding the largest value of the given function or `null` if there are no elements. - */ -public inline fun > BooleanArray.maxBy(selector: (Boolean) -> R): Boolean? { - if (isEmpty()) return null - var maxElem = this[0] - var maxValue = selector(maxElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (maxValue < v) { - maxElem = e - maxValue = v - } - } - return maxElem -} - -/** - * Returns the first element yielding the largest value of the given function or `null` if there are no elements. - */ -public inline fun > CharArray.maxBy(selector: (Char) -> R): Char? { - if (isEmpty()) return null - var maxElem = this[0] - var maxValue = selector(maxElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (maxValue < v) { - maxElem = e - maxValue = v - } - } - return maxElem -} - -/** - * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun Array.maxWith(comparator: Comparator): T? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(max, e) < 0) max = e - } - return max -} - -/** - * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun ByteArray.maxWith(comparator: Comparator): Byte? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(max, e) < 0) max = e - } - return max -} - -/** - * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun ShortArray.maxWith(comparator: Comparator): Short? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(max, e) < 0) max = e - } - return max -} - -/** - * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun IntArray.maxWith(comparator: Comparator): Int? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(max, e) < 0) max = e - } - return max -} - -/** - * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun LongArray.maxWith(comparator: Comparator): Long? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(max, e) < 0) max = e - } - return max -} - -/** - * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun FloatArray.maxWith(comparator: Comparator): Float? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(max, e) < 0) max = e - } - return max -} - -/** - * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun DoubleArray.maxWith(comparator: Comparator): Double? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(max, e) < 0) max = e - } - return max -} - -/** - * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun BooleanArray.maxWith(comparator: Comparator): Boolean? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(max, e) < 0) max = e - } - return max -} - -/** - * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun CharArray.maxWith(comparator: Comparator): Char? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(max, e) < 0) max = e - } - return max -} - -/** - * Returns the smallest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -@SinceKotlin("1.1") -public fun Array.min(): Double? { - if (isEmpty()) return null - var min = this[0] - if (min.isNaN()) return min - for (i in 1..lastIndex) { - val e = this[i] - if (e.isNaN()) return e - if (min > e) min = e - } - return min -} - -/** - * Returns the smallest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -@SinceKotlin("1.1") -public fun Array.min(): Float? { - if (isEmpty()) return null - var min = this[0] - if (min.isNaN()) return min - for (i in 1..lastIndex) { - val e = this[i] - if (e.isNaN()) return e - if (min > e) min = e - } - return min -} - -/** - * Returns the smallest element or `null` if there are no elements. - */ -public fun > Array.min(): T? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (min > e) min = e - } - return min -} - -/** - * Returns the smallest element or `null` if there are no elements. - */ -public fun ByteArray.min(): Byte? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (min > e) min = e - } - return min -} - -/** - * Returns the smallest element or `null` if there are no elements. - */ -public fun ShortArray.min(): Short? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (min > e) min = e - } - return min -} - -/** - * Returns the smallest element or `null` if there are no elements. - */ -public fun IntArray.min(): Int? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (min > e) min = e - } - return min -} - -/** - * Returns the smallest element or `null` if there are no elements. - */ -public fun LongArray.min(): Long? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (min > e) min = e - } - return min -} - -/** - * Returns the smallest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -public fun FloatArray.min(): Float? { - if (isEmpty()) return null - var min = this[0] - if (min.isNaN()) return min - for (i in 1..lastIndex) { - val e = this[i] - if (e.isNaN()) return e - if (min > e) min = e - } - return min -} - -/** - * Returns the smallest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -public fun DoubleArray.min(): Double? { - if (isEmpty()) return null - var min = this[0] - if (min.isNaN()) return min - for (i in 1..lastIndex) { - val e = this[i] - if (e.isNaN()) return e - if (min > e) min = e - } - return min -} - -/** - * Returns the smallest element or `null` if there are no elements. - */ -public fun CharArray.min(): Char? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (min > e) min = e - } - return min -} - -/** - * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. - */ -public inline fun > Array.minBy(selector: (T) -> R): T? { - if (isEmpty()) return null - var minElem = this[0] - var minValue = selector(minElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (minValue > v) { - minElem = e - minValue = v - } - } - return minElem -} - -/** - * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. - */ -public inline fun > ByteArray.minBy(selector: (Byte) -> R): Byte? { - if (isEmpty()) return null - var minElem = this[0] - var minValue = selector(minElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (minValue > v) { - minElem = e - minValue = v - } - } - return minElem -} - -/** - * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. - */ -public inline fun > ShortArray.minBy(selector: (Short) -> R): Short? { - if (isEmpty()) return null - var minElem = this[0] - var minValue = selector(minElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (minValue > v) { - minElem = e - minValue = v - } - } - return minElem -} - -/** - * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. - */ -public inline fun > IntArray.minBy(selector: (Int) -> R): Int? { - if (isEmpty()) return null - var minElem = this[0] - var minValue = selector(minElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (minValue > v) { - minElem = e - minValue = v - } - } - return minElem -} - -/** - * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. - */ -public inline fun > LongArray.minBy(selector: (Long) -> R): Long? { - if (isEmpty()) return null - var minElem = this[0] - var minValue = selector(minElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (minValue > v) { - minElem = e - minValue = v - } - } - return minElem -} - -/** - * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. - */ -public inline fun > FloatArray.minBy(selector: (Float) -> R): Float? { - if (isEmpty()) return null - var minElem = this[0] - var minValue = selector(minElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (minValue > v) { - minElem = e - minValue = v - } - } - return minElem -} - -/** - * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. - */ -public inline fun > DoubleArray.minBy(selector: (Double) -> R): Double? { - if (isEmpty()) return null - var minElem = this[0] - var minValue = selector(minElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (minValue > v) { - minElem = e - minValue = v - } - } - return minElem -} - -/** - * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. - */ -public inline fun > BooleanArray.minBy(selector: (Boolean) -> R): Boolean? { - if (isEmpty()) return null - var minElem = this[0] - var minValue = selector(minElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (minValue > v) { - minElem = e - minValue = v - } - } - return minElem -} - -/** - * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. - */ -public inline fun > CharArray.minBy(selector: (Char) -> R): Char? { - if (isEmpty()) return null - var minElem = this[0] - var minValue = selector(minElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (minValue > v) { - minElem = e - minValue = v - } - } - return minElem -} - -/** - * Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun Array.minWith(comparator: Comparator): T? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(min, e) > 0) min = e - } - return min -} - -/** - * Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun ByteArray.minWith(comparator: Comparator): Byte? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(min, e) > 0) min = e - } - return min -} - -/** - * Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun ShortArray.minWith(comparator: Comparator): Short? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(min, e) > 0) min = e - } - return min -} - -/** - * Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun IntArray.minWith(comparator: Comparator): Int? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(min, e) > 0) min = e - } - return min -} - -/** - * Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun LongArray.minWith(comparator: Comparator): Long? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(min, e) > 0) min = e - } - return min -} - -/** - * Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun FloatArray.minWith(comparator: Comparator): Float? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(min, e) > 0) min = e - } - return min -} - -/** - * Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun DoubleArray.minWith(comparator: Comparator): Double? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(min, e) > 0) min = e - } - return min -} - -/** - * Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun BooleanArray.minWith(comparator: Comparator): Boolean? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(min, e) > 0) min = e - } - return min -} - -/** - * Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun CharArray.minWith(comparator: Comparator): Char? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(min, e) > 0) min = e - } - return min -} - -/** - * Returns `true` if the array has no elements. - */ -public fun Array.none(): Boolean { - for (element in this) return false - return true -} - -/** - * Returns `true` if the array has no elements. - */ -public fun ByteArray.none(): Boolean { - for (element in this) return false - return true -} - -/** - * Returns `true` if the array has no elements. - */ -public fun ShortArray.none(): Boolean { - for (element in this) return false - return true -} - -/** - * Returns `true` if the array has no elements. - */ -public fun IntArray.none(): Boolean { - for (element in this) return false - return true -} - -/** - * Returns `true` if the array has no elements. - */ -public fun LongArray.none(): Boolean { - for (element in this) return false - return true -} - -/** - * Returns `true` if the array has no elements. - */ -public fun FloatArray.none(): Boolean { - for (element in this) return false - return true -} - -/** - * Returns `true` if the array has no elements. - */ -public fun DoubleArray.none(): Boolean { - for (element in this) return false - return true -} - -/** - * Returns `true` if the array has no elements. - */ -public fun BooleanArray.none(): Boolean { - for (element in this) return false - return true -} - -/** - * Returns `true` if the array has no elements. - */ -public fun CharArray.none(): Boolean { - for (element in this) return false - return true -} - -/** - * Returns `true` if no elements match the given [predicate]. - */ -public inline fun Array.none(predicate: (T) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return false - return true -} - -/** - * Returns `true` if no elements match the given [predicate]. - */ -public inline fun ByteArray.none(predicate: (Byte) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return false - return true -} - -/** - * Returns `true` if no elements match the given [predicate]. - */ -public inline fun ShortArray.none(predicate: (Short) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return false - return true -} - -/** - * Returns `true` if no elements match the given [predicate]. - */ -public inline fun IntArray.none(predicate: (Int) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return false - return true -} - -/** - * Returns `true` if no elements match the given [predicate]. - */ -public inline fun LongArray.none(predicate: (Long) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return false - return true -} - -/** - * Returns `true` if no elements match the given [predicate]. - */ -public inline fun FloatArray.none(predicate: (Float) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return false - return true -} - -/** - * Returns `true` if no elements match the given [predicate]. - */ -public inline fun DoubleArray.none(predicate: (Double) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return false - return true -} - -/** - * Returns `true` if no elements match the given [predicate]. - */ -public inline fun BooleanArray.none(predicate: (Boolean) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return false - return true -} - -/** - * Returns `true` if no elements match the given [predicate]. - */ -public inline fun CharArray.none(predicate: (Char) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return false - return true -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun Array.reduce(operation: (acc: S, T) -> S): S { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator: S = this[0] - for (index in 1..lastIndex) { - accumulator = operation(accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun ByteArray.reduce(operation: (acc: Byte, Byte) -> Byte): Byte { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun ShortArray.reduce(operation: (acc: Short, Short) -> Short): Short { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun IntArray.reduce(operation: (acc: Int, Int) -> Int): Int { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun LongArray.reduce(operation: (acc: Long, Long) -> Long): Long { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun FloatArray.reduce(operation: (acc: Float, Float) -> Float): Float { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun DoubleArray.reduce(operation: (acc: Double, Double) -> Double): Double { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun BooleanArray.reduce(operation: (acc: Boolean, Boolean) -> Boolean): Boolean { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun CharArray.reduce(operation: (acc: Char, Char) -> Char): Char { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself and calculates the next accumulator value. - */ -public inline fun Array.reduceIndexed(operation: (index: Int, acc: S, T) -> S): S { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator: S = this[0] - for (index in 1..lastIndex) { - accumulator = operation(index, accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself and calculates the next accumulator value. - */ -public inline fun ByteArray.reduceIndexed(operation: (index: Int, acc: Byte, Byte) -> Byte): Byte { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(index, accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself and calculates the next accumulator value. - */ -public inline fun ShortArray.reduceIndexed(operation: (index: Int, acc: Short, Short) -> Short): Short { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(index, accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself and calculates the next accumulator value. - */ -public inline fun IntArray.reduceIndexed(operation: (index: Int, acc: Int, Int) -> Int): Int { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(index, accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself and calculates the next accumulator value. - */ -public inline fun LongArray.reduceIndexed(operation: (index: Int, acc: Long, Long) -> Long): Long { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(index, accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself and calculates the next accumulator value. - */ -public inline fun FloatArray.reduceIndexed(operation: (index: Int, acc: Float, Float) -> Float): Float { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(index, accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself and calculates the next accumulator value. - */ -public inline fun DoubleArray.reduceIndexed(operation: (index: Int, acc: Double, Double) -> Double): Double { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(index, accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself and calculates the next accumulator value. - */ -public inline fun BooleanArray.reduceIndexed(operation: (index: Int, acc: Boolean, Boolean) -> Boolean): Boolean { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(index, accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right - * to current accumulator value and each element with its index in the original array. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself and calculates the next accumulator value. - */ -public inline fun CharArray.reduceIndexed(operation: (index: Int, acc: Char, Char) -> Char): Char { - if (isEmpty()) - throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(index, accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun Array.reduceRight(operation: (T, acc: S) -> S): S { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator: S = get(index--) - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun ByteArray.reduceRight(operation: (Byte, acc: Byte) -> Byte): Byte { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun ShortArray.reduceRight(operation: (Short, acc: Short) -> Short): Short { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun IntArray.reduceRight(operation: (Int, acc: Int) -> Int): Int { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun LongArray.reduceRight(operation: (Long, acc: Long) -> Long): Long { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun FloatArray.reduceRight(operation: (Float, acc: Float) -> Float): Float { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun DoubleArray.reduceRight(operation: (Double, acc: Double) -> Double): Double { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun BooleanArray.reduceRight(operation: (Boolean, acc: Boolean) -> Boolean): Boolean { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun CharArray.reduceRight(operation: (Char, acc: Char) -> Char): Char { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun Array.reduceRightIndexed(operation: (index: Int, T, acc: S) -> S): S { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator: S = get(index--) - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun ByteArray.reduceRightIndexed(operation: (index: Int, Byte, acc: Byte) -> Byte): Byte { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun ShortArray.reduceRightIndexed(operation: (index: Int, Short, acc: Short) -> Short): Short { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun IntArray.reduceRightIndexed(operation: (index: Int, Int, acc: Int) -> Int): Int { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun LongArray.reduceRightIndexed(operation: (index: Int, Long, acc: Long) -> Long): Long { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun FloatArray.reduceRightIndexed(operation: (index: Int, Float, acc: Float) -> Float): Float { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun DoubleArray.reduceRightIndexed(operation: (index: Int, Double, acc: Double) -> Double): Double { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun BooleanArray.reduceRightIndexed(operation: (index: Int, Boolean, acc: Boolean) -> Boolean): Boolean { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left - * to each element with its index in the original array and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun CharArray.reduceRightIndexed(operation: (index: Int, Char, acc: Char) -> Char): Char { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty array can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Returns first index of [element], or -1 if the array does not contain element. - */ -public fun <@kotlin.internal.OnlyInputTypes T> Array.indexOf(element: T): Int { - if (element == null) { - for (index in indices) { - if (this[index] == null) { - return index - } - } - } else { - for (index in indices) { - if (element == this[index]) { - return index - } - } - } - return -1 -} - -/** - * Returns first index of [element], or -1 if the array does not contain element. - */ -public fun ByteArray.indexOf(element: Byte): Int { - for (index in indices) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns first index of [element], or -1 if the array does not contain element. - */ -public fun ShortArray.indexOf(element: Short): Int { - for (index in indices) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns first index of [element], or -1 if the array does not contain element. - */ -public fun IntArray.indexOf(element: Int): Int { - for (index in indices) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns first index of [element], or -1 if the array does not contain element. - */ -public fun LongArray.indexOf(element: Long): Int { - for (index in indices) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns first index of [element], or -1 if the array does not contain element. - */ -public fun FloatArray.indexOf(element: Float): Int { - for (index in indices) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns first index of [element], or -1 if the array does not contain element. - */ -public fun DoubleArray.indexOf(element: Double): Int { - for (index in indices) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns first index of [element], or -1 if the array does not contain element. - */ -public fun BooleanArray.indexOf(element: Boolean): Int { - for (index in indices) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns first index of [element], or -1 if the array does not contain element. - */ -public fun CharArray.indexOf(element: Char): Int { - for (index in indices) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun Array.indexOfFirst(predicate: (T) -> Boolean): Int { - for (index in indices) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun ByteArray.indexOfFirst(predicate: (Byte) -> Boolean): Int { - for (index in indices) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun ShortArray.indexOfFirst(predicate: (Short) -> Boolean): Int { - for (index in indices) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun IntArray.indexOfFirst(predicate: (Int) -> Boolean): Int { - for (index in indices) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun LongArray.indexOfFirst(predicate: (Long) -> Boolean): Int { - for (index in indices) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun FloatArray.indexOfFirst(predicate: (Float) -> Boolean): Int { - for (index in indices) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun DoubleArray.indexOfFirst(predicate: (Double) -> Boolean): Int { - for (index in indices) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun BooleanArray.indexOfFirst(predicate: (Boolean) -> Boolean): Int { - for (index in indices) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the first element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun CharArray.indexOfFirst(predicate: (Char) -> Boolean): Int { - for (index in indices) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun Array.indexOfLast(predicate: (T) -> Boolean): Int { - for (index in indices.reversed()) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun ByteArray.indexOfLast(predicate: (Byte) -> Boolean): Int { - for (index in indices.reversed()) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun ShortArray.indexOfLast(predicate: (Short) -> Boolean): Int { - for (index in indices.reversed()) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun IntArray.indexOfLast(predicate: (Int) -> Boolean): Int { - for (index in indices.reversed()) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun LongArray.indexOfLast(predicate: (Long) -> Boolean): Int { - for (index in indices.reversed()) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun FloatArray.indexOfLast(predicate: (Float) -> Boolean): Int { - for (index in indices.reversed()) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun DoubleArray.indexOfLast(predicate: (Double) -> Boolean): Int { - for (index in indices.reversed()) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun BooleanArray.indexOfLast(predicate: (Boolean) -> Boolean): Int { - for (index in indices.reversed()) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the last element matching the given [predicate], or -1 if the array does not contain such element. - */ -public inline fun CharArray.indexOfLast(predicate: (Char) -> Boolean): Int { - for (index in indices.reversed()) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns the last element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun Array.last(): T { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[lastIndex] -} - -/** - * Returns the last element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun ByteArray.last(): Byte { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[lastIndex] -} - -/** - * Returns the last element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun ShortArray.last(): Short { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[lastIndex] -} - -/** - * Returns the last element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun IntArray.last(): Int { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[lastIndex] -} - -/** - * Returns the last element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun LongArray.last(): Long { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[lastIndex] -} - -/** - * Returns the last element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun FloatArray.last(): Float { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[lastIndex] -} - -/** - * Returns the last element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun DoubleArray.last(): Double { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[lastIndex] -} - -/** - * Returns the last element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun BooleanArray.last(): Boolean { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[lastIndex] -} - -/** - * Returns the last element. - * @throws [NoSuchElementException] if the array is empty. - */ -public fun CharArray.last(): Char { - if (isEmpty()) - throw NoSuchElementException("Array is empty.") - return this[lastIndex] -} - -/** - * Returns the last element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun Array.last(predicate: (T) -> Boolean): T { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the last element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun ByteArray.last(predicate: (Byte) -> Boolean): Byte { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the last element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun ShortArray.last(predicate: (Short) -> Boolean): Short { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the last element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun IntArray.last(predicate: (Int) -> Boolean): Int { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the last element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun LongArray.last(predicate: (Long) -> Boolean): Long { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the last element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun FloatArray.last(predicate: (Float) -> Boolean): Float { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the last element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun DoubleArray.last(predicate: (Double) -> Boolean): Double { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the last element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun BooleanArray.last(predicate: (Boolean) -> Boolean): Boolean { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns the last element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun CharArray.last(predicate: (Char) -> Boolean): Char { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - throw NoSuchElementException("Array contains no element matching the predicate.") -} - -/** - * Returns a list containing all elements not matching the given [predicate]. - */ -public inline fun Array.filterNot(predicate: (T) -> Boolean): List { - return filterNotTo(ArrayList(), predicate) -} - -/** - * Returns a list containing all elements not matching the given [predicate]. - */ -public inline fun ByteArray.filterNot(predicate: (Byte) -> Boolean): List { - return filterNotTo(ArrayList(), predicate) -} - -/** - * Returns a list containing all elements not matching the given [predicate]. - */ -public inline fun ShortArray.filterNot(predicate: (Short) -> Boolean): List { - return filterNotTo(ArrayList(), predicate) -} - -/** - * Returns a list containing all elements not matching the given [predicate]. - */ -public inline fun IntArray.filterNot(predicate: (Int) -> Boolean): List { - return filterNotTo(ArrayList(), predicate) -} - -/** - * Returns a list containing all elements not matching the given [predicate]. - */ -public inline fun LongArray.filterNot(predicate: (Long) -> Boolean): List { - return filterNotTo(ArrayList(), predicate) -} - -/** - * Returns a list containing all elements not matching the given [predicate]. - */ -public inline fun FloatArray.filterNot(predicate: (Float) -> Boolean): List { - return filterNotTo(ArrayList(), predicate) -} - -/** - * Returns a list containing all elements not matching the given [predicate]. - */ -public inline fun DoubleArray.filterNot(predicate: (Double) -> Boolean): List { - return filterNotTo(ArrayList(), predicate) -} - -/** - * Returns a list containing all elements not matching the given [predicate]. - */ -public inline fun BooleanArray.filterNot(predicate: (Boolean) -> Boolean): List { - return filterNotTo(ArrayList(), predicate) -} - -/** - * Returns a list containing all elements not matching the given [predicate]. - */ -public inline fun CharArray.filterNot(predicate: (Char) -> Boolean): List { - return filterNotTo(ArrayList(), predicate) -} - -/** - * Appends all elements not matching the given [predicate] to the given [destination]. - */ -public inline fun > Array.filterNotTo(destination: C, predicate: (T) -> Boolean): C { - for (element in this) if (!predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements not matching the given [predicate] to the given [destination]. - */ -public inline fun > ByteArray.filterNotTo(destination: C, predicate: (Byte) -> Boolean): C { - for (element in this) if (!predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements not matching the given [predicate] to the given [destination]. - */ -public inline fun > ShortArray.filterNotTo(destination: C, predicate: (Short) -> Boolean): C { - for (element in this) if (!predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements not matching the given [predicate] to the given [destination]. - */ -public inline fun > IntArray.filterNotTo(destination: C, predicate: (Int) -> Boolean): C { - for (element in this) if (!predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements not matching the given [predicate] to the given [destination]. - */ -public inline fun > LongArray.filterNotTo(destination: C, predicate: (Long) -> Boolean): C { - for (element in this) if (!predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements not matching the given [predicate] to the given [destination]. - */ -public inline fun > FloatArray.filterNotTo(destination: C, predicate: (Float) -> Boolean): C { - for (element in this) if (!predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements not matching the given [predicate] to the given [destination]. - */ -public inline fun > DoubleArray.filterNotTo(destination: C, predicate: (Double) -> Boolean): C { - for (element in this) if (!predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements not matching the given [predicate] to the given [destination]. - */ -public inline fun > BooleanArray.filterNotTo(destination: C, predicate: (Boolean) -> Boolean): C { - for (element in this) if (!predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements not matching the given [predicate] to the given [destination]. - */ -public inline fun > CharArray.filterNotTo(destination: C, predicate: (Char) -> Boolean): C { - for (element in this) if (!predicate(element)) destination.add(element) - return destination -} - -/** - * Returns a list containing all elements that are not `null`. - */ -public fun Array.filterNotNull(): List { - return filterNotNullTo(ArrayList()) -} - -/** - * Appends all elements that are not `null` to the given [destination]. - */ -public fun , T : Any> Array.filterNotNullTo(destination: C): C { - for (element in this) if (element != null) destination.add(element) - return destination -} - -/** - * Returns the first element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun Array.find(predicate: (T) -> Boolean): T? { - return firstOrNull(predicate) -} - -/** - * Returns the first element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun ByteArray.find(predicate: (Byte) -> Boolean): Byte? { - return firstOrNull(predicate) -} - -/** - * Returns the first element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun ShortArray.find(predicate: (Short) -> Boolean): Short? { - return firstOrNull(predicate) -} - -/** - * Returns the first element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun IntArray.find(predicate: (Int) -> Boolean): Int? { - return firstOrNull(predicate) -} - -/** - * Returns the first element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun LongArray.find(predicate: (Long) -> Boolean): Long? { - return firstOrNull(predicate) -} - -/** - * Returns the first element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun FloatArray.find(predicate: (Float) -> Boolean): Float? { - return firstOrNull(predicate) -} - -/** - * Returns the first element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun DoubleArray.find(predicate: (Double) -> Boolean): Double? { - return firstOrNull(predicate) -} - -/** - * Returns the first element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun BooleanArray.find(predicate: (Boolean) -> Boolean): Boolean? { - return firstOrNull(predicate) -} - -/** - * Returns the first element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun CharArray.find(predicate: (Char) -> Boolean): Char? { - return firstOrNull(predicate) -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun Array.findLast(predicate: (T) -> Boolean): T? { - return lastOrNull(predicate) -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun ByteArray.findLast(predicate: (Byte) -> Boolean): Byte? { - return lastOrNull(predicate) -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun ShortArray.findLast(predicate: (Short) -> Boolean): Short? { - return lastOrNull(predicate) -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun IntArray.findLast(predicate: (Int) -> Boolean): Int? { - return lastOrNull(predicate) -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun LongArray.findLast(predicate: (Long) -> Boolean): Long? { - return lastOrNull(predicate) -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun FloatArray.findLast(predicate: (Float) -> Boolean): Float? { - return lastOrNull(predicate) -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun DoubleArray.findLast(predicate: (Double) -> Boolean): Double? { - return lastOrNull(predicate) -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun BooleanArray.findLast(predicate: (Boolean) -> Boolean): Boolean? { - return lastOrNull(predicate) -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun CharArray.findLast(predicate: (Char) -> Boolean): Char? { - return lastOrNull(predicate) -} - -/** - * Returns the first element, or `null` if the array is empty. - */ -public fun Array.firstOrNull(): T? { - return if (isEmpty()) null else this[0] -} - -/** - * Returns the first element, or `null` if the array is empty. - */ -public fun ByteArray.firstOrNull(): Byte? { - return if (isEmpty()) null else this[0] -} - -/** - * Returns the first element, or `null` if the array is empty. - */ -public fun ShortArray.firstOrNull(): Short? { - return if (isEmpty()) null else this[0] -} - -/** - * Returns the first element, or `null` if the array is empty. - */ -public fun IntArray.firstOrNull(): Int? { - return if (isEmpty()) null else this[0] -} - -/** - * Returns the first element, or `null` if the array is empty. - */ -public fun LongArray.firstOrNull(): Long? { - return if (isEmpty()) null else this[0] -} - -/** - * Returns the first element, or `null` if the array is empty. - */ -public fun FloatArray.firstOrNull(): Float? { - return if (isEmpty()) null else this[0] -} - -/** - * Returns the first element, or `null` if the array is empty. - */ -public fun DoubleArray.firstOrNull(): Double? { - return if (isEmpty()) null else this[0] -} - -/** - * Returns the first element, or `null` if the array is empty. - */ -public fun BooleanArray.firstOrNull(): Boolean? { - return if (isEmpty()) null else this[0] -} - -/** - * Returns the first element, or `null` if the array is empty. - */ -public fun CharArray.firstOrNull(): Char? { - return if (isEmpty()) null else this[0] -} - -/** - * Returns the first element matching the given [predicate], or `null` if element was not found. - */ -public inline fun Array.firstOrNull(predicate: (T) -> Boolean): T? { - for (element in this) if (predicate(element)) return element - return null -} - -/** - * Returns the first element matching the given [predicate], or `null` if element was not found. - */ -public inline fun ByteArray.firstOrNull(predicate: (Byte) -> Boolean): Byte? { - for (element in this) if (predicate(element)) return element - return null -} - -/** - * Returns the first element matching the given [predicate], or `null` if element was not found. - */ -public inline fun ShortArray.firstOrNull(predicate: (Short) -> Boolean): Short? { - for (element in this) if (predicate(element)) return element - return null -} - -/** - * Returns the first element matching the given [predicate], or `null` if element was not found. - */ -public inline fun IntArray.firstOrNull(predicate: (Int) -> Boolean): Int? { - for (element in this) if (predicate(element)) return element - return null -} - -/** - * Returns the first element matching the given [predicate], or `null` if element was not found. - */ -public inline fun LongArray.firstOrNull(predicate: (Long) -> Boolean): Long? { - for (element in this) if (predicate(element)) return element - return null -} - -/** - * Returns the first element matching the given [predicate], or `null` if element was not found. - */ -public inline fun FloatArray.firstOrNull(predicate: (Float) -> Boolean): Float? { - for (element in this) if (predicate(element)) return element - return null -} - -/** - * Returns the first element matching the given [predicate], or `null` if element was not found. - */ -public inline fun DoubleArray.firstOrNull(predicate: (Double) -> Boolean): Double? { - for (element in this) if (predicate(element)) return element - return null -} - -/** - * Returns the first element matching the given [predicate], or `null` if element was not found. - */ -public inline fun BooleanArray.firstOrNull(predicate: (Boolean) -> Boolean): Boolean? { - for (element in this) if (predicate(element)) return element - return null -} - -/** - * Returns the first element matching the given [predicate], or `null` if element was not found. - */ -public inline fun CharArray.firstOrNull(predicate: (Char) -> Boolean): Char? { - for (element in this) if (predicate(element)) return element - return null -} - -/** - * Returns the last element, or `null` if the array is empty. - */ -public fun Array.lastOrNull(): T? { - return if (isEmpty()) null else this[size - 1] -} - -/** - * Returns the last element, or `null` if the array is empty. - */ -public fun ByteArray.lastOrNull(): Byte? { - return if (isEmpty()) null else this[size - 1] -} - -/** - * Returns the last element, or `null` if the array is empty. - */ -public fun ShortArray.lastOrNull(): Short? { - return if (isEmpty()) null else this[size - 1] -} - -/** - * Returns the last element, or `null` if the array is empty. - */ -public fun IntArray.lastOrNull(): Int? { - return if (isEmpty()) null else this[size - 1] -} - -/** - * Returns the last element, or `null` if the array is empty. - */ -public fun LongArray.lastOrNull(): Long? { - return if (isEmpty()) null else this[size - 1] -} - -/** - * Returns the last element, or `null` if the array is empty. - */ -public fun FloatArray.lastOrNull(): Float? { - return if (isEmpty()) null else this[size - 1] -} - -/** - * Returns the last element, or `null` if the array is empty. - */ -public fun DoubleArray.lastOrNull(): Double? { - return if (isEmpty()) null else this[size - 1] -} - -/** - * Returns the last element, or `null` if the array is empty. - */ -public fun BooleanArray.lastOrNull(): Boolean? { - return if (isEmpty()) null else this[size - 1] -} - -/** - * Returns the last element, or `null` if the array is empty. - */ -public fun CharArray.lastOrNull(): Char? { - return if (isEmpty()) null else this[size - 1] -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun Array.lastOrNull(predicate: (T) -> Boolean): T? { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - return null -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun ByteArray.lastOrNull(predicate: (Byte) -> Boolean): Byte? { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - return null -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun ShortArray.lastOrNull(predicate: (Short) -> Boolean): Short? { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - return null -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun IntArray.lastOrNull(predicate: (Int) -> Boolean): Int? { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - return null -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun LongArray.lastOrNull(predicate: (Long) -> Boolean): Long? { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - return null -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun FloatArray.lastOrNull(predicate: (Float) -> Boolean): Float? { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - return null -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun DoubleArray.lastOrNull(predicate: (Double) -> Boolean): Double? { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - return null -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun BooleanArray.lastOrNull(predicate: (Boolean) -> Boolean): Boolean? { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - return null -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun CharArray.lastOrNull(predicate: (Char) -> Boolean): Char? { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - return null -} - -/** - * Returns the single element, or throws an exception if the array is empty or has more than one element. - */ -public fun Array.single(): T { - return when (size) { - 0 -> throw NoSuchElementException("Array is empty.") - 1 -> this[0] - else -> throw IllegalArgumentException("Array has more than one element.") - } -} - -/** - * Returns the single element, or throws an exception if the array is empty or has more than one element. - */ -public fun ByteArray.single(): Byte { - return when (size) { - 0 -> throw NoSuchElementException("Array is empty.") - 1 -> this[0] - else -> throw IllegalArgumentException("Array has more than one element.") - } -} - -/** - * Returns the single element, or throws an exception if the array is empty or has more than one element. - */ -public fun ShortArray.single(): Short { - return when (size) { - 0 -> throw NoSuchElementException("Array is empty.") - 1 -> this[0] - else -> throw IllegalArgumentException("Array has more than one element.") - } -} - -/** - * Returns the single element, or throws an exception if the array is empty or has more than one element. - */ -public fun IntArray.single(): Int { - return when (size) { - 0 -> throw NoSuchElementException("Array is empty.") - 1 -> this[0] - else -> throw IllegalArgumentException("Array has more than one element.") - } -} - -/** - * Returns the single element, or throws an exception if the array is empty or has more than one element. - */ -public fun LongArray.single(): Long { - return when (size) { - 0 -> throw NoSuchElementException("Array is empty.") - 1 -> this[0] - else -> throw IllegalArgumentException("Array has more than one element.") - } -} - -/** - * Returns the single element, or throws an exception if the array is empty or has more than one element. - */ -public fun DoubleArray.single(): Double { - return when (size) { - 0 -> throw NoSuchElementException("Array is empty.") - 1 -> this[0] - else -> throw IllegalArgumentException("Array has more than one element.") - } -} - -/** - * Returns the single element, or throws an exception if the array is empty or has more than one element. - */ -public fun BooleanArray.single(): Boolean { - return when (size) { - 0 -> throw NoSuchElementException("Array is empty.") - 1 -> this[0] - else -> throw IllegalArgumentException("Array has more than one element.") - } -} - -/** - * Returns the single element, or throws an exception if the array is empty or has more than one element. - */ -public fun CharArray.single(): Char { - return when (size) { - 0 -> throw NoSuchElementException("Array is empty.") - 1 -> this[0] - else -> throw IllegalArgumentException("Array has more than one element.") - } -} - -/** - * Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. - */ -public inline fun Array.single(predicate: (T) -> Boolean): T { - var single: T? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) throw IllegalArgumentException("Array contains more than one matching element.") - single = element - found = true - } - } - if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") - @Suppress("UNCHECKED_CAST") - return single as T -} - -/** - * Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. - */ -public inline fun ByteArray.single(predicate: (Byte) -> Boolean): Byte { - var single: Byte? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) throw IllegalArgumentException("Array contains more than one matching element.") - single = element - found = true - } - } - if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") - return single as Byte -} - -/** - * Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. - */ -public inline fun ShortArray.single(predicate: (Short) -> Boolean): Short { - var single: Short? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) throw IllegalArgumentException("Array contains more than one matching element.") - single = element - found = true - } - } - if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") - return single as Short -} - -/** - * Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. - */ -public inline fun IntArray.single(predicate: (Int) -> Boolean): Int { - var single: Int? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) throw IllegalArgumentException("Array contains more than one matching element.") - single = element - found = true - } - } - if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") - return single as Int -} - -/** - * Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. - */ -public inline fun LongArray.single(predicate: (Long) -> Boolean): Long { - var single: Long? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) throw IllegalArgumentException("Array contains more than one matching element.") - single = element - found = true - } - } - if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") - return single as Long -} - -/** - * Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. - */ -public inline fun FloatArray.single(predicate: (Float) -> Boolean): Float { - var single: Float? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) throw IllegalArgumentException("Array contains more than one matching element.") - single = element - found = true - } - } - if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") - return single as Float -} - -/** - * Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. - */ -public inline fun DoubleArray.single(predicate: (Double) -> Boolean): Double { - var single: Double? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) throw IllegalArgumentException("Array contains more than one matching element.") - single = element - found = true - } - } - if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") - return single as Double -} - -/** - * Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. - */ -public inline fun BooleanArray.single(predicate: (Boolean) -> Boolean): Boolean { - var single: Boolean? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) throw IllegalArgumentException("Array contains more than one matching element.") - single = element - found = true - } - } - if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") - return single as Boolean -} - -/** - * Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. - */ -public inline fun CharArray.single(predicate: (Char) -> Boolean): Char { - var single: Char? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) throw IllegalArgumentException("Array contains more than one matching element.") - single = element - found = true - } - } - if (!found) throw NoSuchElementException("Array contains no element matching the predicate.") - return single as Char -} - -/** - * Returns single element, or `null` if the array is empty or has more than one element. - */ -public fun Array.singleOrNull(): T? { - return if (size == 1) this[0] else null -} - -/** - * Returns single element, or `null` if the array is empty or has more than one element. - */ -public fun ByteArray.singleOrNull(): Byte? { - return if (size == 1) this[0] else null -} - -/** - * Returns single element, or `null` if the array is empty or has more than one element. - */ -public fun ShortArray.singleOrNull(): Short? { - return if (size == 1) this[0] else null -} - -/** - * Returns single element, or `null` if the array is empty or has more than one element. - */ -public fun IntArray.singleOrNull(): Int? { - return if (size == 1) this[0] else null -} - -/** - * Returns single element, or `null` if the array is empty or has more than one element. - */ -public fun LongArray.singleOrNull(): Long? { - return if (size == 1) this[0] else null -} - -/** - * Returns single element, or `null` if the array is empty or has more than one element. - */ -public fun FloatArray.singleOrNull(): Float? { - return if (size == 1) this[0] else null -} - -/** - * Returns single element, or `null` if the array is empty or has more than one element. - */ -public fun DoubleArray.singleOrNull(): Double? { - return if (size == 1) this[0] else null -} - -/** - * Returns single element, or `null` if the array is empty or has more than one element. - */ -public fun BooleanArray.singleOrNull(): Boolean? { - return if (size == 1) this[0] else null -} - -/** - * Returns single element, or `null` if the array is empty or has more than one element. - */ -public fun CharArray.singleOrNull(): Char? { - return if (size == 1) this[0] else null -} - -/** - * Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. - */ -public inline fun Array.singleOrNull(predicate: (T) -> Boolean): T? { - var single: T? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) return null - single = element - found = true - } - } - if (!found) return null - return single -} - -/** - * Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. - */ -public inline fun ByteArray.singleOrNull(predicate: (Byte) -> Boolean): Byte? { - var single: Byte? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) return null - single = element - found = true - } - } - if (!found) return null - return single -} - -/** - * Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. - */ -public inline fun ShortArray.singleOrNull(predicate: (Short) -> Boolean): Short? { - var single: Short? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) return null - single = element - found = true - } - } - if (!found) return null - return single -} - -/** - * Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. - */ -public inline fun IntArray.singleOrNull(predicate: (Int) -> Boolean): Int? { - var single: Int? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) return null - single = element - found = true - } - } - if (!found) return null - return single -} - -/** - * Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. - */ -public inline fun LongArray.singleOrNull(predicate: (Long) -> Boolean): Long? { - var single: Long? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) return null - single = element - found = true - } - } - if (!found) return null - return single -} - -/** - * Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. - */ -public inline fun FloatArray.singleOrNull(predicate: (Float) -> Boolean): Float? { - var single: Float? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) return null - single = element - found = true - } - } - if (!found) return null - return single -} - -/** - * Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. - */ -public inline fun DoubleArray.singleOrNull(predicate: (Double) -> Boolean): Double? { - var single: Double? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) return null - single = element - found = true - } - } - if (!found) return null - return single -} - -/** - * Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. - */ -public inline fun BooleanArray.singleOrNull(predicate: (Boolean) -> Boolean): Boolean? { - var single: Boolean? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) return null - single = element - found = true - } - } - if (!found) return null - return single -} - -/** - * Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. - */ -public inline fun CharArray.singleOrNull(predicate: (Char) -> Boolean): Char? { - var single: Char? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) return null - single = element - found = true - } - } - if (!found) return null - return single -} - -/** - * Returns a list containing all elements except first [n] elements. - */ -public fun Array.drop(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return takeLast((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except first [n] elements. - */ -public fun ByteArray.drop(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return takeLast((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except first [n] elements. - */ -public fun ShortArray.drop(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return takeLast((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except first [n] elements. - */ -public fun IntArray.drop(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return takeLast((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except first [n] elements. - */ -public fun LongArray.drop(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return takeLast((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except first [n] elements. - */ -public fun FloatArray.drop(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return takeLast((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except first [n] elements. - */ -public fun DoubleArray.drop(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return takeLast((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except first [n] elements. - */ -public fun BooleanArray.drop(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return takeLast((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except first [n] elements. - */ -public fun CharArray.drop(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return takeLast((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except last [n] elements. - */ -public fun Array.dropLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return take((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except last [n] elements. - */ -public fun ByteArray.dropLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return take((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except last [n] elements. - */ -public fun ShortArray.dropLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return take((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except last [n] elements. - */ -public fun IntArray.dropLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return take((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except last [n] elements. - */ -public fun LongArray.dropLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return take((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except last [n] elements. - */ -public fun FloatArray.dropLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return take((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except last [n] elements. - */ -public fun DoubleArray.dropLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return take((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except last [n] elements. - */ -public fun BooleanArray.dropLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return take((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except last [n] elements. - */ -public fun CharArray.dropLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return take((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except last elements that satisfy the given [predicate]. - */ -public inline fun Array.dropLastWhile(predicate: (T) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return take(index + 1) - } - } - return emptyList() -} - -/** - * Returns a list containing all elements except last elements that satisfy the given [predicate]. - */ -public inline fun ByteArray.dropLastWhile(predicate: (Byte) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return take(index + 1) - } - } - return emptyList() -} - -/** - * Returns a list containing all elements except last elements that satisfy the given [predicate]. - */ -public inline fun ShortArray.dropLastWhile(predicate: (Short) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return take(index + 1) - } - } - return emptyList() -} - -/** - * Returns a list containing all elements except last elements that satisfy the given [predicate]. - */ -public inline fun IntArray.dropLastWhile(predicate: (Int) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return take(index + 1) - } - } - return emptyList() -} - -/** - * Returns a list containing all elements except last elements that satisfy the given [predicate]. - */ -public inline fun LongArray.dropLastWhile(predicate: (Long) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return take(index + 1) - } - } - return emptyList() -} - -/** - * Returns a list containing all elements except last elements that satisfy the given [predicate]. - */ -public inline fun FloatArray.dropLastWhile(predicate: (Float) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return take(index + 1) - } - } - return emptyList() -} - -/** - * Returns a list containing all elements except last elements that satisfy the given [predicate]. - */ -public inline fun DoubleArray.dropLastWhile(predicate: (Double) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return take(index + 1) - } - } - return emptyList() -} - -/** - * Returns a list containing all elements except last elements that satisfy the given [predicate]. - */ -public inline fun BooleanArray.dropLastWhile(predicate: (Boolean) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return take(index + 1) - } - } - return emptyList() -} - -/** - * Returns a list containing all elements except last elements that satisfy the given [predicate]. - */ -public inline fun CharArray.dropLastWhile(predicate: (Char) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return take(index + 1) - } - } - return emptyList() -} - -/** - * Returns a list containing all elements except first elements that satisfy the given [predicate]. - */ -public inline fun Array.dropWhile(predicate: (T) -> Boolean): List { - var yielding = false - val list = ArrayList() - for (item in this) - if (yielding) - list.add(item) - else if (!predicate(item)) { - list.add(item) - yielding = true - } - return list -} - -/** - * Returns a list containing all elements except first elements that satisfy the given [predicate]. - */ -public inline fun ByteArray.dropWhile(predicate: (Byte) -> Boolean): List { - var yielding = false - val list = ArrayList() - for (item in this) - if (yielding) - list.add(item) - else if (!predicate(item)) { - list.add(item) - yielding = true - } - return list -} - -/** - * Returns a list containing all elements except first elements that satisfy the given [predicate]. - */ -public inline fun ShortArray.dropWhile(predicate: (Short) -> Boolean): List { - var yielding = false - val list = ArrayList() - for (item in this) - if (yielding) - list.add(item) - else if (!predicate(item)) { - list.add(item) - yielding = true - } - return list -} - -/** - * Returns a list containing all elements except first elements that satisfy the given [predicate]. - */ -public inline fun IntArray.dropWhile(predicate: (Int) -> Boolean): List { - var yielding = false - val list = ArrayList() - for (item in this) - if (yielding) - list.add(item) - else if (!predicate(item)) { - list.add(item) - yielding = true - } - return list -} - -/** - * Returns a list containing all elements except first elements that satisfy the given [predicate]. - */ -public inline fun LongArray.dropWhile(predicate: (Long) -> Boolean): List { - var yielding = false - val list = ArrayList() - for (item in this) - if (yielding) - list.add(item) - else if (!predicate(item)) { - list.add(item) - yielding = true - } - return list -} - -/** - * Returns a list containing all elements except first elements that satisfy the given [predicate]. - */ -public inline fun FloatArray.dropWhile(predicate: (Float) -> Boolean): List { - var yielding = false - val list = ArrayList() - for (item in this) - if (yielding) - list.add(item) - else if (!predicate(item)) { - list.add(item) - yielding = true - } - return list -} - -/** - * Returns a list containing all elements except first elements that satisfy the given [predicate]. - */ -public inline fun DoubleArray.dropWhile(predicate: (Double) -> Boolean): List { - var yielding = false - val list = ArrayList() - for (item in this) - if (yielding) - list.add(item) - else if (!predicate(item)) { - list.add(item) - yielding = true - } - return list -} - -/** - * Returns a list containing all elements except first elements that satisfy the given [predicate]. - */ -public inline fun BooleanArray.dropWhile(predicate: (Boolean) -> Boolean): List { - var yielding = false - val list = ArrayList() - for (item in this) - if (yielding) - list.add(item) - else if (!predicate(item)) { - list.add(item) - yielding = true - } - return list -} - -/** - * Returns a list containing all elements except first elements that satisfy the given [predicate]. - */ -public inline fun CharArray.dropWhile(predicate: (Char) -> Boolean): List { - var yielding = false - val list = ArrayList() - for (item in this) - if (yielding) - list.add(item) - else if (!predicate(item)) { - list.add(item) - yielding = true - } - return list -} - -/** - * Returns a list containing only elements matching the given [predicate]. - */ -public inline fun Array.filter(predicate: (T) -> Boolean): List { - return filterTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - */ -public inline fun ByteArray.filter(predicate: (Byte) -> Boolean): List { - return filterTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - */ -public inline fun ShortArray.filter(predicate: (Short) -> Boolean): List { - return filterTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - */ -public inline fun IntArray.filter(predicate: (Int) -> Boolean): List { - return filterTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - */ -public inline fun LongArray.filter(predicate: (Long) -> Boolean): List { - return filterTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - */ -public inline fun FloatArray.filter(predicate: (Float) -> Boolean): List { - return filterTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - */ -public inline fun DoubleArray.filter(predicate: (Double) -> Boolean): List { - return filterTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - */ -public inline fun BooleanArray.filter(predicate: (Boolean) -> Boolean): List { - return filterTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - */ -public inline fun CharArray.filter(predicate: (Char) -> Boolean): List { - return filterTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun Array.filterIndexed(predicate: (index: Int, T) -> Boolean): List { - return filterIndexedTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun ByteArray.filterIndexed(predicate: (index: Int, Byte) -> Boolean): List { - return filterIndexedTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun ShortArray.filterIndexed(predicate: (index: Int, Short) -> Boolean): List { - return filterIndexedTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun IntArray.filterIndexed(predicate: (index: Int, Int) -> Boolean): List { - return filterIndexedTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun LongArray.filterIndexed(predicate: (index: Int, Long) -> Boolean): List { - return filterIndexedTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun FloatArray.filterIndexed(predicate: (index: Int, Float) -> Boolean): List { - return filterIndexedTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun DoubleArray.filterIndexed(predicate: (index: Int, Double) -> Boolean): List { - return filterIndexedTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun BooleanArray.filterIndexed(predicate: (index: Int, Boolean) -> Boolean): List { - return filterIndexedTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun CharArray.filterIndexed(predicate: (index: Int, Char) -> Boolean): List { - return filterIndexedTo(ArrayList(), predicate) -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun > Array.filterIndexedTo(destination: C, predicate: (index: Int, T) -> Boolean): C { - forEachIndexed { index, element -> - if (predicate(index, element)) destination.add(element) - } - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun > ByteArray.filterIndexedTo(destination: C, predicate: (index: Int, Byte) -> Boolean): C { - forEachIndexed { index, element -> - if (predicate(index, element)) destination.add(element) - } - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun > ShortArray.filterIndexedTo(destination: C, predicate: (index: Int, Short) -> Boolean): C { - forEachIndexed { index, element -> - if (predicate(index, element)) destination.add(element) - } - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun > IntArray.filterIndexedTo(destination: C, predicate: (index: Int, Int) -> Boolean): C { - forEachIndexed { index, element -> - if (predicate(index, element)) destination.add(element) - } - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun > LongArray.filterIndexedTo(destination: C, predicate: (index: Int, Long) -> Boolean): C { - forEachIndexed { index, element -> - if (predicate(index, element)) destination.add(element) - } - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun > FloatArray.filterIndexedTo(destination: C, predicate: (index: Int, Float) -> Boolean): C { - forEachIndexed { index, element -> - if (predicate(index, element)) destination.add(element) - } - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun > DoubleArray.filterIndexedTo(destination: C, predicate: (index: Int, Double) -> Boolean): C { - forEachIndexed { index, element -> - if (predicate(index, element)) destination.add(element) - } - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun > BooleanArray.filterIndexedTo(destination: C, predicate: (index: Int, Boolean) -> Boolean): C { - forEachIndexed { index, element -> - if (predicate(index, element)) destination.add(element) - } - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun > CharArray.filterIndexedTo(destination: C, predicate: (index: Int, Char) -> Boolean): C { - forEachIndexed { index, element -> - if (predicate(index, element)) destination.add(element) - } - return destination -} - -/** - * Returns a list containing all elements that are instances of specified type parameter R. - */ -public inline fun Array<*>.filterIsInstance(): List<@kotlin.internal.NoInfer R> { - return filterIsInstanceTo(ArrayList()) -} - -/** - * Appends all elements that are instances of specified type parameter R to the given [destination]. - */ -public inline fun > Array<*>.filterIsInstanceTo(destination: C): C { - for (element in this) if (element is R) destination.add(element) - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - */ -public inline fun > Array.filterTo(destination: C, predicate: (T) -> Boolean): C { - for (element in this) if (predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - */ -public inline fun > ByteArray.filterTo(destination: C, predicate: (Byte) -> Boolean): C { - for (element in this) if (predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - */ -public inline fun > ShortArray.filterTo(destination: C, predicate: (Short) -> Boolean): C { - for (element in this) if (predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - */ -public inline fun > IntArray.filterTo(destination: C, predicate: (Int) -> Boolean): C { - for (element in this) if (predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - */ -public inline fun > LongArray.filterTo(destination: C, predicate: (Long) -> Boolean): C { - for (element in this) if (predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - */ -public inline fun > FloatArray.filterTo(destination: C, predicate: (Float) -> Boolean): C { - for (element in this) if (predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - */ -public inline fun > DoubleArray.filterTo(destination: C, predicate: (Double) -> Boolean): C { - for (element in this) if (predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - */ -public inline fun > BooleanArray.filterTo(destination: C, predicate: (Boolean) -> Boolean): C { - for (element in this) if (predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - */ -public inline fun > CharArray.filterTo(destination: C, predicate: (Char) -> Boolean): C { - for (element in this) if (predicate(element)) destination.add(element) - return destination -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun Array.slice(indices: IntRange): List { - if (indices.isEmpty()) return listOf() - return copyOfRange(indices.start, indices.endInclusive + 1).asList() -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun ByteArray.slice(indices: IntRange): List { - if (indices.isEmpty()) return listOf() - return copyOfRange(indices.start, indices.endInclusive + 1).asList() -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun ShortArray.slice(indices: IntRange): List { - if (indices.isEmpty()) return listOf() - return copyOfRange(indices.start, indices.endInclusive + 1).asList() -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun IntArray.slice(indices: IntRange): List { - if (indices.isEmpty()) return listOf() - return copyOfRange(indices.start, indices.endInclusive + 1).asList() -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun LongArray.slice(indices: IntRange): List { - if (indices.isEmpty()) return listOf() - return copyOfRange(indices.start, indices.endInclusive + 1).asList() -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun FloatArray.slice(indices: IntRange): List { - if (indices.isEmpty()) return listOf() - return copyOfRange(indices.start, indices.endInclusive + 1).asList() -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun DoubleArray.slice(indices: IntRange): List { - if (indices.isEmpty()) return listOf() - return copyOfRange(indices.start, indices.endInclusive + 1).asList() -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun BooleanArray.slice(indices: IntRange): List { - if (indices.isEmpty()) return listOf() - return copyOfRange(indices.start, indices.endInclusive + 1).asList() -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun CharArray.slice(indices: IntRange): List { - if (indices.isEmpty()) return listOf() - return copyOfRange(indices.start, indices.endInclusive + 1).asList() -} - -/** - * Returns a list containing elements at specified [indices]. - */ -public fun Array.slice(indices: Iterable): List { - val size = indices.collectionSizeOrDefault(10) - if (size == 0) return emptyList() - val list = ArrayList(size) - for (index in indices) { - list.add(get(index)) - } - return list -} - -/** - * Returns a list containing elements at specified [indices]. - */ -public fun ByteArray.slice(indices: Iterable): List { - val size = indices.collectionSizeOrDefault(10) - if (size == 0) return emptyList() - val list = ArrayList(size) - for (index in indices) { - list.add(get(index)) - } - return list -} - -/** - * Returns a list containing elements at specified [indices]. - */ -public fun ShortArray.slice(indices: Iterable): List { - val size = indices.collectionSizeOrDefault(10) - if (size == 0) return emptyList() - val list = ArrayList(size) - for (index in indices) { - list.add(get(index)) - } - return list -} - -/** - * Returns a list containing elements at specified [indices]. - */ -public fun IntArray.slice(indices: Iterable): List { - val size = indices.collectionSizeOrDefault(10) - if (size == 0) return emptyList() - val list = ArrayList(size) - for (index in indices) { - list.add(get(index)) - } - return list -} - -/** - * Returns a list containing elements at specified [indices]. - */ -public fun LongArray.slice(indices: Iterable): List { - val size = indices.collectionSizeOrDefault(10) - if (size == 0) return emptyList() - val list = ArrayList(size) - for (index in indices) { - list.add(get(index)) - } - return list -} - -/** - * Returns a list containing elements at specified [indices]. - */ -public fun FloatArray.slice(indices: Iterable): List { - val size = indices.collectionSizeOrDefault(10) - if (size == 0) return emptyList() - val list = ArrayList(size) - for (index in indices) { - list.add(get(index)) - } - return list -} - -/** - * Returns a list containing elements at specified [indices]. - */ -public fun DoubleArray.slice(indices: Iterable): List { - val size = indices.collectionSizeOrDefault(10) - if (size == 0) return emptyList() - val list = ArrayList(size) - for (index in indices) { - list.add(get(index)) - } - return list -} - -/** - * Returns a list containing elements at specified [indices]. - */ -public fun BooleanArray.slice(indices: Iterable): List { - val size = indices.collectionSizeOrDefault(10) - if (size == 0) return emptyList() - val list = ArrayList(size) - for (index in indices) { - list.add(get(index)) - } - return list -} - -/** - * Returns a list containing elements at specified [indices]. - */ -public fun CharArray.slice(indices: Iterable): List { - val size = indices.collectionSizeOrDefault(10) - if (size == 0) return emptyList() - val list = ArrayList(size) - for (index in indices) { - list.add(get(index)) - } - return list -} - -/** - * Returns an array containing elements of this array at specified [indices]. - */ -public fun Array.sliceArray(indices: Collection): Array { - val result = arrayOfUninitializedElements(indices.size) - var targetIndex = 0 - for (sourceIndex in indices) { - result[targetIndex++] = this[sourceIndex] - } - return result -} - -/** - * Returns an array containing elements of this array at specified [indices]. - */ -public fun ByteArray.sliceArray(indices: Collection): ByteArray { - val result = ByteArray(indices.size) - var targetIndex = 0 - for (sourceIndex in indices) { - result[targetIndex++] = this[sourceIndex] - } - return result -} - -/** - * Returns an array containing elements of this array at specified [indices]. - */ -public fun ShortArray.sliceArray(indices: Collection): ShortArray { - val result = ShortArray(indices.size) - var targetIndex = 0 - for (sourceIndex in indices) { - result[targetIndex++] = this[sourceIndex] - } - return result -} - -/** - * Returns an array containing elements of this array at specified [indices]. - */ -public fun IntArray.sliceArray(indices: Collection): IntArray { - val result = IntArray(indices.size) - var targetIndex = 0 - for (sourceIndex in indices) { - result[targetIndex++] = this[sourceIndex] - } - return result -} - -/** - * Returns an array containing elements of this array at specified [indices]. - */ -public fun LongArray.sliceArray(indices: Collection): LongArray { - val result = LongArray(indices.size) - var targetIndex = 0 - for (sourceIndex in indices) { - result[targetIndex++] = this[sourceIndex] - } - return result -} - -/** - * Returns an array containing elements of this array at specified [indices]. - */ -public fun FloatArray.sliceArray(indices: Collection): FloatArray { - val result = FloatArray(indices.size) - var targetIndex = 0 - for (sourceIndex in indices) { - result[targetIndex++] = this[sourceIndex] - } - return result -} - -/** - * Returns an array containing elements of this array at specified [indices]. - */ -public fun DoubleArray.sliceArray(indices: Collection): DoubleArray { - val result = DoubleArray(indices.size) - var targetIndex = 0 - for (sourceIndex in indices) { - result[targetIndex++] = this[sourceIndex] - } - return result -} - -/** - * Returns an array containing elements of this array at specified [indices]. - */ -public fun BooleanArray.sliceArray(indices: Collection): BooleanArray { - val result = BooleanArray(indices.size) - var targetIndex = 0 - for (sourceIndex in indices) { - result[targetIndex++] = this[sourceIndex] - } - return result -} - -/** - * Returns an array containing elements of this array at specified [indices]. - */ -public fun CharArray.sliceArray(indices: Collection): CharArray { - val result = CharArray(indices.size) - var targetIndex = 0 - for (sourceIndex in indices) { - result[targetIndex++] = this[sourceIndex] - } - return result -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun Array.sliceArray(indices: IntRange): Array { - if (indices.isEmpty()) return copyOfRange(0, 0) - return copyOfRange(indices.start, indices.endInclusive + 1) -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun ByteArray.sliceArray(indices: IntRange): ByteArray { - if (indices.isEmpty()) return ByteArray(0) - return copyOfRange(indices.start, indices.endInclusive + 1) -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun ShortArray.sliceArray(indices: IntRange): ShortArray { - if (indices.isEmpty()) return ShortArray(0) - return copyOfRange(indices.start, indices.endInclusive + 1) -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun IntArray.sliceArray(indices: IntRange): IntArray { - if (indices.isEmpty()) return IntArray(0) - return copyOfRange(indices.start, indices.endInclusive + 1) -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun LongArray.sliceArray(indices: IntRange): LongArray { - if (indices.isEmpty()) return LongArray(0) - return copyOfRange(indices.start, indices.endInclusive + 1) -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun FloatArray.sliceArray(indices: IntRange): FloatArray { - if (indices.isEmpty()) return FloatArray(0) - return copyOfRange(indices.start, indices.endInclusive + 1) -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun DoubleArray.sliceArray(indices: IntRange): DoubleArray { - if (indices.isEmpty()) return DoubleArray(0) - return copyOfRange(indices.start, indices.endInclusive + 1) -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun BooleanArray.sliceArray(indices: IntRange): BooleanArray { - if (indices.isEmpty()) return BooleanArray(0) - return copyOfRange(indices.start, indices.endInclusive + 1) -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun CharArray.sliceArray(indices: IntRange): CharArray { - if (indices.isEmpty()) return CharArray(0) - return copyOfRange(indices.start, indices.endInclusive + 1) -} - -/** - * Returns a list containing first [n] elements. - */ -public fun Array.take(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - if (n >= size) return toList() - if (n == 1) return listOf(this[0]) - var count = 0 - val list = ArrayList(n) - for (item in this) { - if (count++ == n) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first [n] elements. - */ -public fun ByteArray.take(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - if (n >= size) return toList() - if (n == 1) return listOf(this[0]) - var count = 0 - val list = ArrayList(n) - for (item in this) { - if (count++ == n) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first [n] elements. - */ -public fun ShortArray.take(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - if (n >= size) return toList() - if (n == 1) return listOf(this[0]) - var count = 0 - val list = ArrayList(n) - for (item in this) { - if (count++ == n) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first [n] elements. - */ -public fun IntArray.take(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - if (n >= size) return toList() - if (n == 1) return listOf(this[0]) - var count = 0 - val list = ArrayList(n) - for (item in this) { - if (count++ == n) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first [n] elements. - */ -public fun LongArray.take(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - if (n >= size) return toList() - if (n == 1) return listOf(this[0]) - var count = 0 - val list = ArrayList(n) - for (item in this) { - if (count++ == n) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first [n] elements. - */ -public fun FloatArray.take(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - if (n >= size) return toList() - if (n == 1) return listOf(this[0]) - var count = 0 - val list = ArrayList(n) - for (item in this) { - if (count++ == n) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first [n] elements. - */ -public fun DoubleArray.take(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - if (n >= size) return toList() - if (n == 1) return listOf(this[0]) - var count = 0 - val list = ArrayList(n) - for (item in this) { - if (count++ == n) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first [n] elements. - */ -public fun BooleanArray.take(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - if (n >= size) return toList() - if (n == 1) return listOf(this[0]) - var count = 0 - val list = ArrayList(n) - for (item in this) { - if (count++ == n) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first [n] elements. - */ -public fun CharArray.take(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - if (n >= size) return toList() - if (n == 1) return listOf(this[0]) - var count = 0 - val list = ArrayList(n) - for (item in this) { - if (count++ == n) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing last [n] elements. - */ -public fun Array.takeLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - val size = size - if (n >= size) return toList() - if (n == 1) return listOf(this[size - 1]) - val list = ArrayList(n) - for (index in size - n .. size - 1) - list.add(this[index]) - return list -} - -/** - * Returns a list containing last [n] elements. - */ -public fun ByteArray.takeLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - val size = size - if (n >= size) return toList() - if (n == 1) return listOf(this[size - 1]) - val list = ArrayList(n) - for (index in size - n .. size - 1) - list.add(this[index]) - return list -} - -/** - * Returns a list containing last [n] elements. - */ -public fun ShortArray.takeLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - val size = size - if (n >= size) return toList() - if (n == 1) return listOf(this[size - 1]) - val list = ArrayList(n) - for (index in size - n .. size - 1) - list.add(this[index]) - return list -} - -/** - * Returns a list containing last [n] elements. - */ -public fun IntArray.takeLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - val size = size - if (n >= size) return toList() - if (n == 1) return listOf(this[size - 1]) - val list = ArrayList(n) - for (index in size - n .. size - 1) - list.add(this[index]) - return list -} - -/** - * Returns a list containing last [n] elements. - */ -public fun LongArray.takeLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - val size = size - if (n >= size) return toList() - if (n == 1) return listOf(this[size - 1]) - val list = ArrayList(n) - for (index in size - n .. size - 1) - list.add(this[index]) - return list -} - -/** - * Returns a list containing last [n] elements. - */ -public fun FloatArray.takeLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - val size = size - if (n >= size) return toList() - if (n == 1) return listOf(this[size - 1]) - val list = ArrayList(n) - for (index in size - n .. size - 1) - list.add(this[index]) - return list -} - -/** - * Returns a list containing last [n] elements. - */ -public fun DoubleArray.takeLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - val size = size - if (n >= size) return toList() - if (n == 1) return listOf(this[size - 1]) - val list = ArrayList(n) - for (index in size - n .. size - 1) - list.add(this[index]) - return list -} - -/** - * Returns a list containing last [n] elements. - */ -public fun BooleanArray.takeLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - val size = size - if (n >= size) return toList() - if (n == 1) return listOf(this[size - 1]) - val list = ArrayList(n) - for (index in size - n .. size - 1) - list.add(this[index]) - return list -} - -/** - * Returns a list containing last [n] elements. - */ -public fun CharArray.takeLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - val size = size - if (n >= size) return toList() - if (n == 1) return listOf(this[size - 1]) - val list = ArrayList(n) - for (index in size - n .. size - 1) - list.add(this[index]) - return list -} - -/** - * Returns a list containing last elements satisfying the given [predicate]. - */ -public inline fun Array.takeLastWhile(predicate: (T) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return drop(index + 1) - } - } - return toList() -} - -/** - * Returns a list containing last elements satisfying the given [predicate]. - */ -public inline fun ByteArray.takeLastWhile(predicate: (Byte) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return drop(index + 1) - } - } - return toList() -} - -/** - * Returns a list containing last elements satisfying the given [predicate]. - */ -public inline fun ShortArray.takeLastWhile(predicate: (Short) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return drop(index + 1) - } - } - return toList() -} - -/** - * Returns a list containing last elements satisfying the given [predicate]. - */ -public inline fun IntArray.takeLastWhile(predicate: (Int) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return drop(index + 1) - } - } - return toList() -} - -/** - * Returns a list containing last elements satisfying the given [predicate]. - */ -public inline fun LongArray.takeLastWhile(predicate: (Long) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return drop(index + 1) - } - } - return toList() -} - -/** - * Returns a list containing last elements satisfying the given [predicate]. - */ -public inline fun FloatArray.takeLastWhile(predicate: (Float) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return drop(index + 1) - } - } - return toList() -} - -/** - * Returns a list containing last elements satisfying the given [predicate]. - */ -public inline fun DoubleArray.takeLastWhile(predicate: (Double) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return drop(index + 1) - } - } - return toList() -} - -/** - * Returns a list containing last elements satisfying the given [predicate]. - */ -public inline fun BooleanArray.takeLastWhile(predicate: (Boolean) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return drop(index + 1) - } - } - return toList() -} - -/** - * Returns a list containing last elements satisfying the given [predicate]. - */ -public inline fun CharArray.takeLastWhile(predicate: (Char) -> Boolean): List { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return drop(index + 1) - } - } - return toList() -} - -/** - * Returns a list containing first elements satisfying the given [predicate]. - */ -public inline fun Array.takeWhile(predicate: (T) -> Boolean): List { - val list = ArrayList() - for (item in this) { - if (!predicate(item)) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first elements satisfying the given [predicate]. - */ -public inline fun ByteArray.takeWhile(predicate: (Byte) -> Boolean): List { - val list = ArrayList() - for (item in this) { - if (!predicate(item)) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first elements satisfying the given [predicate]. - */ -public inline fun ShortArray.takeWhile(predicate: (Short) -> Boolean): List { - val list = ArrayList() - for (item in this) { - if (!predicate(item)) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first elements satisfying the given [predicate]. - */ -public inline fun IntArray.takeWhile(predicate: (Int) -> Boolean): List { - val list = ArrayList() - for (item in this) { - if (!predicate(item)) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first elements satisfying the given [predicate]. - */ -public inline fun LongArray.takeWhile(predicate: (Long) -> Boolean): List { - val list = ArrayList() - for (item in this) { - if (!predicate(item)) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first elements satisfying the given [predicate]. - */ -public inline fun FloatArray.takeWhile(predicate: (Float) -> Boolean): List { - val list = ArrayList() - for (item in this) { - if (!predicate(item)) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first elements satisfying the given [predicate]. - */ -public inline fun DoubleArray.takeWhile(predicate: (Double) -> Boolean): List { - val list = ArrayList() - for (item in this) { - if (!predicate(item)) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first elements satisfying the given [predicate]. - */ -public inline fun BooleanArray.takeWhile(predicate: (Boolean) -> Boolean): List { - val list = ArrayList() - for (item in this) { - if (!predicate(item)) - break - list.add(item) - } - return list -} - -/** - * Returns a list containing first elements satisfying the given [predicate]. - */ -public inline fun CharArray.takeWhile(predicate: (Char) -> Boolean): List { - val list = ArrayList() - for (item in this) { - if (!predicate(item)) - break - list.add(item) - } - return list -} - -/** - * Reverses elements in the array in-place. - */ -public fun Array.reverse(): Unit { - val midPoint = (size / 2) - 1 - if (midPoint < 0) return - var reverseIndex = lastIndex - for (index in 0..midPoint) { - val tmp = this[index] - this[index] = this[reverseIndex] - this[reverseIndex] = tmp - reverseIndex-- - } -} - -/** - * Reverses elements in the array in-place. - */ -public fun ByteArray.reverse(): Unit { - val midPoint = (size / 2) - 1 - if (midPoint < 0) return - var reverseIndex = lastIndex - for (index in 0..midPoint) { - val tmp = this[index] - this[index] = this[reverseIndex] - this[reverseIndex] = tmp - reverseIndex-- - } -} - -/** - * Reverses elements in the array in-place. - */ -public fun ShortArray.reverse(): Unit { - val midPoint = (size / 2) - 1 - if (midPoint < 0) return - var reverseIndex = lastIndex - for (index in 0..midPoint) { - val tmp = this[index] - this[index] = this[reverseIndex] - this[reverseIndex] = tmp - reverseIndex-- - } -} - -/** - * Reverses elements in the array in-place. - */ -public fun IntArray.reverse(): Unit { - val midPoint = (size / 2) - 1 - if (midPoint < 0) return - var reverseIndex = lastIndex - for (index in 0..midPoint) { - val tmp = this[index] - this[index] = this[reverseIndex] - this[reverseIndex] = tmp - reverseIndex-- - } -} - -/** - * Reverses elements in the array in-place. - */ -public fun LongArray.reverse(): Unit { - val midPoint = (size / 2) - 1 - if (midPoint < 0) return - var reverseIndex = lastIndex - for (index in 0..midPoint) { - val tmp = this[index] - this[index] = this[reverseIndex] - this[reverseIndex] = tmp - reverseIndex-- - } -} - -/** - * Reverses elements in the array in-place. - */ -public fun FloatArray.reverse(): Unit { - val midPoint = (size / 2) - 1 - if (midPoint < 0) return - var reverseIndex = lastIndex - for (index in 0..midPoint) { - val tmp = this[index] - this[index] = this[reverseIndex] - this[reverseIndex] = tmp - reverseIndex-- - } -} - -/** - * Reverses elements in the array in-place. - */ -public fun DoubleArray.reverse(): Unit { - val midPoint = (size / 2) - 1 - if (midPoint < 0) return - var reverseIndex = lastIndex - for (index in 0..midPoint) { - val tmp = this[index] - this[index] = this[reverseIndex] - this[reverseIndex] = tmp - reverseIndex-- - } -} - -/** - * Reverses elements in the array in-place. - */ -public fun BooleanArray.reverse(): Unit { - val midPoint = (size / 2) - 1 - if (midPoint < 0) return - var reverseIndex = lastIndex - for (index in 0..midPoint) { - val tmp = this[index] - this[index] = this[reverseIndex] - this[reverseIndex] = tmp - reverseIndex-- - } -} - -/** - * Reverses elements in the array in-place. - */ -public fun CharArray.reverse(): Unit { - val midPoint = (size / 2) - 1 - if (midPoint < 0) return - var reverseIndex = lastIndex - for (index in 0..midPoint) { - val tmp = this[index] - this[index] = this[reverseIndex] - this[reverseIndex] = tmp - reverseIndex-- - } -} - -/** - * Returns a list with elements in reversed order. - */ -public fun Array.reversed(): List { - if (isEmpty()) return emptyList() - val list = toMutableList() - list.reverse() - return list -} - -/** - * Returns a list with elements in reversed order. - */ -public fun ByteArray.reversed(): List { - if (isEmpty()) return emptyList() - val list = toMutableList() - list.reverse() - return list -} - -/** - * Returns a list with elements in reversed order. - */ -public fun ShortArray.reversed(): List { - if (isEmpty()) return emptyList() - val list = toMutableList() - list.reverse() - return list -} - -/** - * Returns a list with elements in reversed order. - */ -public fun IntArray.reversed(): List { - if (isEmpty()) return emptyList() - val list = toMutableList() - list.reverse() - return list -} - -/** - * Returns a list with elements in reversed order. - */ -public fun LongArray.reversed(): List { - if (isEmpty()) return emptyList() - val list = toMutableList() - list.reverse() - return list -} - -/** - * Returns a list with elements in reversed order. - */ -public fun FloatArray.reversed(): List { - if (isEmpty()) return emptyList() - val list = toMutableList() - list.reverse() - return list -} - -/** - * Returns a list with elements in reversed order. - */ -public fun DoubleArray.reversed(): List { - if (isEmpty()) return emptyList() - val list = toMutableList() - list.reverse() - return list -} - -/** - * Returns a list with elements in reversed order. - */ -public fun BooleanArray.reversed(): List { - if (isEmpty()) return emptyList() - val list = toMutableList() - list.reverse() - return list -} - -/** - * Returns a list with elements in reversed order. - */ -public fun CharArray.reversed(): List { - if (isEmpty()) return emptyList() - val list = toMutableList() - list.reverse() - return list -} - -/** - * Returns an array with elements of this array in reversed order. - */ -public fun Array.reversedArray(): Array { - if (isEmpty()) return this - val result = arrayOfUninitializedElements(size) - val lastIndex = lastIndex - for (i in 0..lastIndex) - result[lastIndex - i] = this[i] - return result -} - -/** - * Returns an array with elements of this array in reversed order. - */ -public fun ByteArray.reversedArray(): ByteArray { - if (isEmpty()) return this - val result = ByteArray(size) - val lastIndex = lastIndex - for (i in 0..lastIndex) - result[lastIndex - i] = this[i] - return result -} - -/** - * Returns an array with elements of this array in reversed order. - */ -public fun ShortArray.reversedArray(): ShortArray { - if (isEmpty()) return this - val result = ShortArray(size) - val lastIndex = lastIndex - for (i in 0..lastIndex) - result[lastIndex - i] = this[i] - return result -} - -/** - * Returns an array with elements of this array in reversed order. - */ -public fun IntArray.reversedArray(): IntArray { - if (isEmpty()) return this - val result = IntArray(size) - val lastIndex = lastIndex - for (i in 0..lastIndex) - result[lastIndex - i] = this[i] - return result -} - -/** - * Returns an array with elements of this array in reversed order. - */ -public fun LongArray.reversedArray(): LongArray { - if (isEmpty()) return this - val result = LongArray(size) - val lastIndex = lastIndex - for (i in 0..lastIndex) - result[lastIndex - i] = this[i] - return result -} - -/** - * Returns an array with elements of this array in reversed order. - */ -public fun FloatArray.reversedArray(): FloatArray { - if (isEmpty()) return this - val result = FloatArray(size) - val lastIndex = lastIndex - for (i in 0..lastIndex) - result[lastIndex - i] = this[i] - return result -} - -/** - * Returns an array with elements of this array in reversed order. - */ -public fun DoubleArray.reversedArray(): DoubleArray { - if (isEmpty()) return this - val result = DoubleArray(size) - val lastIndex = lastIndex - for (i in 0..lastIndex) - result[lastIndex - i] = this[i] - return result -} - -/** - * Returns an array with elements of this array in reversed order. - */ -public fun BooleanArray.reversedArray(): BooleanArray { - if (isEmpty()) return this - val result = BooleanArray(size) - val lastIndex = lastIndex - for (i in 0..lastIndex) - result[lastIndex - i] = this[i] - return result -} - -/** - * Returns an array with elements of this array in reversed order. - */ -public fun CharArray.reversedArray(): CharArray { - if (isEmpty()) return this - val result = CharArray(size) - val lastIndex = lastIndex - for (i in 0..lastIndex) - result[lastIndex - i] = this[i] - return result -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element in the original array. - */ -public inline fun Array.map(transform: (T) -> R): List { - return mapTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element in the original array. - */ -public inline fun ByteArray.map(transform: (Byte) -> R): List { - return mapTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element in the original array. - */ -public inline fun ShortArray.map(transform: (Short) -> R): List { - return mapTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element in the original array. - */ -public inline fun IntArray.map(transform: (Int) -> R): List { - return mapTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element in the original array. - */ -public inline fun LongArray.map(transform: (Long) -> R): List { - return mapTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element in the original array. - */ -public inline fun FloatArray.map(transform: (Float) -> R): List { - return mapTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element in the original array. - */ -public inline fun DoubleArray.map(transform: (Double) -> R): List { - return mapTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element in the original array. - */ -public inline fun BooleanArray.map(transform: (Boolean) -> R): List { - return mapTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element in the original array. - */ -public inline fun CharArray.map(transform: (Char) -> R): List { - return mapTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element and its index in the original array. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun Array.mapIndexed(transform: (index: Int, T) -> R): List { - return mapIndexedTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element and its index in the original array. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun ByteArray.mapIndexed(transform: (index: Int, Byte) -> R): List { - return mapIndexedTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element and its index in the original array. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun ShortArray.mapIndexed(transform: (index: Int, Short) -> R): List { - return mapIndexedTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element and its index in the original array. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun IntArray.mapIndexed(transform: (index: Int, Int) -> R): List { - return mapIndexedTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element and its index in the original array. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun LongArray.mapIndexed(transform: (index: Int, Long) -> R): List { - return mapIndexedTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element and its index in the original array. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun FloatArray.mapIndexed(transform: (index: Int, Float) -> R): List { - return mapIndexedTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element and its index in the original array. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun DoubleArray.mapIndexed(transform: (index: Int, Double) -> R): List { - return mapIndexedTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element and its index in the original array. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun BooleanArray.mapIndexed(transform: (index: Int, Boolean) -> R): List { - return mapIndexedTo(ArrayList(size), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element and its index in the original array. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun CharArray.mapIndexed(transform: (index: Int, Char) -> R): List { - return mapIndexedTo(ArrayList(size), transform) -} - -/** - * Returns a list containing only the non-null results of applying the given [transform] function - * to each element and its index in the original array. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun Array.mapIndexedNotNull(transform: (index: Int, T) -> R?): List { - return mapIndexedNotNullTo(ArrayList(), transform) -} - -/** - * Applies the given [transform] function to each element and its index in the original array - * and appends only the non-null results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > Array.mapIndexedNotNullTo(destination: C, transform: (index: Int, T) -> R?): C { - forEachIndexed { index, element -> transform(index, element)?.let { destination.add(it) } } - return destination -} - -/** - * Applies the given [transform] function to each element and its index in the original array - * and appends the results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > Array.mapIndexedTo(destination: C, transform: (index: Int, T) -> R): C { - var index = 0 - for (item in this) - destination.add(transform(index++, item)) - return destination -} - -/** - * Applies the given [transform] function to each element and its index in the original array - * and appends the results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > ByteArray.mapIndexedTo(destination: C, transform: (index: Int, Byte) -> R): C { - var index = 0 - for (item in this) - destination.add(transform(index++, item)) - return destination -} - -/** - * Applies the given [transform] function to each element and its index in the original array - * and appends the results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > ShortArray.mapIndexedTo(destination: C, transform: (index: Int, Short) -> R): C { - var index = 0 - for (item in this) - destination.add(transform(index++, item)) - return destination -} - -/** - * Applies the given [transform] function to each element and its index in the original array - * and appends the results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > IntArray.mapIndexedTo(destination: C, transform: (index: Int, Int) -> R): C { - var index = 0 - for (item in this) - destination.add(transform(index++, item)) - return destination -} - -/** - * Applies the given [transform] function to each element and its index in the original array - * and appends the results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > LongArray.mapIndexedTo(destination: C, transform: (index: Int, Long) -> R): C { - var index = 0 - for (item in this) - destination.add(transform(index++, item)) - return destination -} - -/** - * Applies the given [transform] function to each element and its index in the original array - * and appends the results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > FloatArray.mapIndexedTo(destination: C, transform: (index: Int, Float) -> R): C { - var index = 0 - for (item in this) - destination.add(transform(index++, item)) - return destination -} - -/** - * Applies the given [transform] function to each element and its index in the original array - * and appends the results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > DoubleArray.mapIndexedTo(destination: C, transform: (index: Int, Double) -> R): C { - var index = 0 - for (item in this) - destination.add(transform(index++, item)) - return destination -} - -/** - * Applies the given [transform] function to each element and its index in the original array - * and appends the results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > BooleanArray.mapIndexedTo(destination: C, transform: (index: Int, Boolean) -> R): C { - var index = 0 - for (item in this) - destination.add(transform(index++, item)) - return destination -} - -/** - * Applies the given [transform] function to each element and its index in the original array - * and appends the results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > CharArray.mapIndexedTo(destination: C, transform: (index: Int, Char) -> R): C { - var index = 0 - for (item in this) - destination.add(transform(index++, item)) - return destination -} - -/** - * Returns a list containing only the non-null results of applying the given [transform] function - * to each element in the original array. - */ -public inline fun Array.mapNotNull(transform: (T) -> R?): List { - return mapNotNullTo(ArrayList(), transform) -} - -/** - * Applies the given [transform] function to each element in the original array - * and appends only the non-null results to the given [destination]. - */ -public inline fun > Array.mapNotNullTo(destination: C, transform: (T) -> R?): C { - forEach { element -> transform(element)?.let { destination.add(it) } } - return destination -} - -/** - * Applies the given [transform] function to each element of the original array - * and appends the results to the given [destination]. - */ -public inline fun > Array.mapTo(destination: C, transform: (T) -> R): C { - for (item in this) - destination.add(transform(item)) - return destination -} - -/** - * Applies the given [transform] function to each element of the original array - * and appends the results to the given [destination]. - */ -public inline fun > ByteArray.mapTo(destination: C, transform: (Byte) -> R): C { - for (item in this) - destination.add(transform(item)) - return destination -} - -/** - * Applies the given [transform] function to each element of the original array - * and appends the results to the given [destination]. - */ -public inline fun > ShortArray.mapTo(destination: C, transform: (Short) -> R): C { - for (item in this) - destination.add(transform(item)) - return destination -} - -/** - * Applies the given [transform] function to each element of the original array - * and appends the results to the given [destination]. - */ -public inline fun > IntArray.mapTo(destination: C, transform: (Int) -> R): C { - for (item in this) - destination.add(transform(item)) - return destination -} - -/** - * Applies the given [transform] function to each element of the original array - * and appends the results to the given [destination]. - */ -public inline fun > LongArray.mapTo(destination: C, transform: (Long) -> R): C { - for (item in this) - destination.add(transform(item)) - return destination -} - -/** - * Applies the given [transform] function to each element of the original array - * and appends the results to the given [destination]. - */ -public inline fun > FloatArray.mapTo(destination: C, transform: (Float) -> R): C { - for (item in this) - destination.add(transform(item)) - return destination -} - -/** - * Applies the given [transform] function to each element of the original array - * and appends the results to the given [destination]. - */ -public inline fun > DoubleArray.mapTo(destination: C, transform: (Double) -> R): C { - for (item in this) - destination.add(transform(item)) - return destination -} - -/** - * Applies the given [transform] function to each element of the original array - * and appends the results to the given [destination]. - */ -public inline fun > BooleanArray.mapTo(destination: C, transform: (Boolean) -> R): C { - for (item in this) - destination.add(transform(item)) - return destination -} - -/** - * Applies the given [transform] function to each element of the original array - * and appends the results to the given [destination]. - */ -public inline fun > CharArray.mapTo(destination: C, transform: (Char) -> R): C { - for (item in this) - destination.add(transform(item)) - return destination -} - -/** - * Returns a lazy [Iterable] of [IndexedValue] for each element of the original array. - */ -public fun Array.withIndex(): Iterable> { - return IndexingIterable { iterator() } -} - -/** - * Returns a lazy [Iterable] of [IndexedValue] for each element of the original array. - */ -public fun ByteArray.withIndex(): Iterable> { - return IndexingIterable { iterator() } -} - -/** - * Returns a lazy [Iterable] of [IndexedValue] for each element of the original array. - */ -public fun ShortArray.withIndex(): Iterable> { - return IndexingIterable { iterator() } -} - -/** - * Returns a lazy [Iterable] of [IndexedValue] for each element of the original array. - */ -public fun IntArray.withIndex(): Iterable> { - return IndexingIterable { iterator() } -} - -/** - * Returns a lazy [Iterable] of [IndexedValue] for each element of the original array. - */ -public fun LongArray.withIndex(): Iterable> { - return IndexingIterable { iterator() } -} - -/** - * Returns a lazy [Iterable] of [IndexedValue] for each element of the original array. - */ -public fun FloatArray.withIndex(): Iterable> { - return IndexingIterable { iterator() } -} - -/** - * Returns a lazy [Iterable] of [IndexedValue] for each element of the original array. - */ -public fun DoubleArray.withIndex(): Iterable> { - return IndexingIterable { iterator() } -} - -/** - * Returns a lazy [Iterable] of [IndexedValue] for each element of the original array. - */ -public fun BooleanArray.withIndex(): Iterable> { - return IndexingIterable { iterator() } -} - -/** - * Returns a lazy [Iterable] of [IndexedValue] for each element of the original array. - */ -public fun CharArray.withIndex(): Iterable> { - return IndexingIterable { iterator() } -} - -/** - * Returns a list containing only distinct elements from the given array. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public fun Array.distinct(): List { - return this.toMutableSet().toList() -} - -/** - * Returns a list containing only distinct elements from the given array. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public fun ByteArray.distinct(): List { - return this.toMutableSet().toList() -} - -/** - * Returns a list containing only distinct elements from the given array. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public fun ShortArray.distinct(): List { - return this.toMutableSet().toList() -} - -/** - * Returns a list containing only distinct elements from the given array. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public fun IntArray.distinct(): List { - return this.toMutableSet().toList() -} - -/** - * Returns a list containing only distinct elements from the given array. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public fun LongArray.distinct(): List { - return this.toMutableSet().toList() -} - -/** - * Returns a list containing only distinct elements from the given array. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public fun FloatArray.distinct(): List { - return this.toMutableSet().toList() -} - -/** - * Returns a list containing only distinct elements from the given array. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public fun DoubleArray.distinct(): List { - return this.toMutableSet().toList() -} - -/** - * Returns a list containing only distinct elements from the given array. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public fun BooleanArray.distinct(): List { - return this.toMutableSet().toList() -} - -/** - * Returns a list containing only distinct elements from the given array. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public fun CharArray.distinct(): List { - return this.toMutableSet().toList() -} - -/** - * Returns a list containing only elements from the given array - * having distinct keys returned by the given [selector] function. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public inline fun Array.distinctBy(selector: (T) -> K): List { - val set = HashSet() - val list = ArrayList() - for (e in this) { - val key = selector(e) - if (set.add(key)) - list.add(e) - } - return list -} - -/** - * Returns a list containing only elements from the given array - * having distinct keys returned by the given [selector] function. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public inline fun ByteArray.distinctBy(selector: (Byte) -> K): List { - val set = HashSet() - val list = ArrayList() - for (e in this) { - val key = selector(e) - if (set.add(key)) - list.add(e) - } - return list -} - -/** - * Returns a list containing only elements from the given array - * having distinct keys returned by the given [selector] function. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public inline fun ShortArray.distinctBy(selector: (Short) -> K): List { - val set = HashSet() - val list = ArrayList() - for (e in this) { - val key = selector(e) - if (set.add(key)) - list.add(e) - } - return list -} - -/** - * Returns a list containing only elements from the given array - * having distinct keys returned by the given [selector] function. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public inline fun IntArray.distinctBy(selector: (Int) -> K): List { - val set = HashSet() - val list = ArrayList() - for (e in this) { - val key = selector(e) - if (set.add(key)) - list.add(e) - } - return list -} - -/** - * Returns a list containing only elements from the given array - * having distinct keys returned by the given [selector] function. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public inline fun LongArray.distinctBy(selector: (Long) -> K): List { - val set = HashSet() - val list = ArrayList() - for (e in this) { - val key = selector(e) - if (set.add(key)) - list.add(e) - } - return list -} - -/** - * Returns a list containing only elements from the given array - * having distinct keys returned by the given [selector] function. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public inline fun FloatArray.distinctBy(selector: (Float) -> K): List { - val set = HashSet() - val list = ArrayList() - for (e in this) { - val key = selector(e) - if (set.add(key)) - list.add(e) - } - return list -} - -/** - * Returns a list containing only elements from the given array - * having distinct keys returned by the given [selector] function. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public inline fun DoubleArray.distinctBy(selector: (Double) -> K): List { - val set = HashSet() - val list = ArrayList() - for (e in this) { - val key = selector(e) - if (set.add(key)) - list.add(e) - } - return list -} - -/** - * Returns a list containing only elements from the given array - * having distinct keys returned by the given [selector] function. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public inline fun BooleanArray.distinctBy(selector: (Boolean) -> K): List { - val set = HashSet() - val list = ArrayList() - for (e in this) { - val key = selector(e) - if (set.add(key)) - list.add(e) - } - return list -} - -/** - * Returns a list containing only elements from the given array - * having distinct keys returned by the given [selector] function. - * - * The elements in the resulting list are in the same order as they were in the source array. - */ -public inline fun CharArray.distinctBy(selector: (Char) -> K): List { - val set = HashSet() - val list = ArrayList() - for (e in this) { - val key = selector(e) - if (set.add(key)) - list.add(e) - } - return list -} - -/** - * Returns a set containing all elements that are contained by both this set and the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun Array.intersect(other: Iterable): Set { - val set = this.toMutableSet() - set.retainAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by both this set and the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun ByteArray.intersect(other: Iterable): Set { - val set = this.toMutableSet() - set.retainAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by both this set and the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun ShortArray.intersect(other: Iterable): Set { - val set = this.toMutableSet() - set.retainAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by both this set and the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun IntArray.intersect(other: Iterable): Set { - val set = this.toMutableSet() - set.retainAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by both this set and the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun LongArray.intersect(other: Iterable): Set { - val set = this.toMutableSet() - set.retainAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by both this set and the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun FloatArray.intersect(other: Iterable): Set { - val set = this.toMutableSet() - set.retainAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by both this set and the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun DoubleArray.intersect(other: Iterable): Set { - val set = this.toMutableSet() - set.retainAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by both this set and the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun BooleanArray.intersect(other: Iterable): Set { - val set = this.toMutableSet() - set.retainAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by both this set and the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun CharArray.intersect(other: Iterable): Set { - val set = this.toMutableSet() - set.retainAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by this array and not contained by the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun Array.subtract(other: Iterable): Set { - val set = this.toMutableSet() - set.removeAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by this array and not contained by the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun ByteArray.subtract(other: Iterable): Set { - val set = this.toMutableSet() - set.removeAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by this array and not contained by the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun ShortArray.subtract(other: Iterable): Set { - val set = this.toMutableSet() - set.removeAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by this array and not contained by the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun IntArray.subtract(other: Iterable): Set { - val set = this.toMutableSet() - set.removeAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by this array and not contained by the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun LongArray.subtract(other: Iterable): Set { - val set = this.toMutableSet() - set.removeAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by this array and not contained by the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun FloatArray.subtract(other: Iterable): Set { - val set = this.toMutableSet() - set.removeAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by this array and not contained by the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun DoubleArray.subtract(other: Iterable): Set { - val set = this.toMutableSet() - set.removeAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by this array and not contained by the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun BooleanArray.subtract(other: Iterable): Set { - val set = this.toMutableSet() - set.removeAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by this array and not contained by the specified collection. - * - * The returned set preserves the element iteration order of the original array. - */ -public infix fun CharArray.subtract(other: Iterable): Set { - val set = this.toMutableSet() - set.removeAll(other) - return set -} - -/** - * Returns a mutable set containing all distinct elements from the given array. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun Array.toMutableSet(): MutableSet { - val set = LinkedHashSet(mapCapacity(size)) - for (item in this) set.add(item) - return set -} - -/** - * Returns a mutable set containing all distinct elements from the given array. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun ByteArray.toMutableSet(): MutableSet { - val set = LinkedHashSet(mapCapacity(size)) - for (item in this) set.add(item) - return set -} - -/** - * Returns a mutable set containing all distinct elements from the given array. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun ShortArray.toMutableSet(): MutableSet { - val set = LinkedHashSet(mapCapacity(size)) - for (item in this) set.add(item) - return set -} - -/** - * Returns a mutable set containing all distinct elements from the given array. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun IntArray.toMutableSet(): MutableSet { - val set = LinkedHashSet(mapCapacity(size)) - for (item in this) set.add(item) - return set -} - -/** - * Returns a mutable set containing all distinct elements from the given array. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun LongArray.toMutableSet(): MutableSet { - val set = LinkedHashSet(mapCapacity(size)) - for (item in this) set.add(item) - return set -} - -/** - * Returns a mutable set containing all distinct elements from the given array. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun FloatArray.toMutableSet(): MutableSet { - val set = LinkedHashSet(mapCapacity(size)) - for (item in this) set.add(item) - return set -} - -/** - * Returns a mutable set containing all distinct elements from the given array. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun DoubleArray.toMutableSet(): MutableSet { - val set = LinkedHashSet(mapCapacity(size)) - for (item in this) set.add(item) - return set -} - -/** - * Returns a mutable set containing all distinct elements from the given array. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun BooleanArray.toMutableSet(): MutableSet { - val set = LinkedHashSet(mapCapacity(size)) - for (item in this) set.add(item) - return set -} - -/** - * Returns a mutable set containing all distinct elements from the given array. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun CharArray.toMutableSet(): MutableSet { - val set = LinkedHashSet(mapCapacity(size)) - for (item in this) set.add(item) - return set -} - -/** - * Returns a set containing all distinct elements from both collections. - * - * The returned set preserves the element iteration order of the original array. - * Those elements of the [other] collection that are unique are iterated in the end - * in the order of the [other] collection. - */ -public infix fun Array.union(other: Iterable): Set { - val set = this.toMutableSet() - set.addAll(other) - return set -} - -/** - * Returns a set containing all distinct elements from both collections. - * - * The returned set preserves the element iteration order of the original array. - * Those elements of the [other] collection that are unique are iterated in the end - * in the order of the [other] collection. - */ -public infix fun ByteArray.union(other: Iterable): Set { - val set = this.toMutableSet() - set.addAll(other) - return set -} - -/** - * Returns a set containing all distinct elements from both collections. - * - * The returned set preserves the element iteration order of the original array. - * Those elements of the [other] collection that are unique are iterated in the end - * in the order of the [other] collection. - */ -public infix fun ShortArray.union(other: Iterable): Set { - val set = this.toMutableSet() - set.addAll(other) - return set -} - -/** - * Returns a set containing all distinct elements from both collections. - * - * The returned set preserves the element iteration order of the original array. - * Those elements of the [other] collection that are unique are iterated in the end - * in the order of the [other] collection. - */ -public infix fun IntArray.union(other: Iterable): Set { - val set = this.toMutableSet() - set.addAll(other) - return set -} - -/** - * Returns a set containing all distinct elements from both collections. - * - * The returned set preserves the element iteration order of the original array. - * Those elements of the [other] collection that are unique are iterated in the end - * in the order of the [other] collection. - */ -public infix fun LongArray.union(other: Iterable): Set { - val set = this.toMutableSet() - set.addAll(other) - return set -} - -/** - * Returns a set containing all distinct elements from both collections. - * - * The returned set preserves the element iteration order of the original array. - * Those elements of the [other] collection that are unique are iterated in the end - * in the order of the [other] collection. - */ -public infix fun FloatArray.union(other: Iterable): Set { - val set = this.toMutableSet() - set.addAll(other) - return set -} - -/** - * Returns a set containing all distinct elements from both collections. - * - * The returned set preserves the element iteration order of the original array. - * Those elements of the [other] collection that are unique are iterated in the end - * in the order of the [other] collection. - */ -public infix fun DoubleArray.union(other: Iterable): Set { - val set = this.toMutableSet() - set.addAll(other) - return set -} - -/** - * Returns a set containing all distinct elements from both collections. - * - * The returned set preserves the element iteration order of the original array. - * Those elements of the [other] collection that are unique are iterated in the end - * in the order of the [other] collection. - */ -public infix fun BooleanArray.union(other: Iterable): Set { - val set = this.toMutableSet() - set.addAll(other) - return set -} - -/** - * Returns a set containing all distinct elements from both collections. - * - * The returned set preserves the element iteration order of the original array. - * Those elements of the [other] collection that are unique are iterated in the end - * in the order of the [other] collection. - */ -public infix fun CharArray.union(other: Iterable): Set { - val set = this.toMutableSet() - set.addAll(other) - return set -} - -/** - * Returns an average value of elements in the array. - */ -public fun Array.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the array. - */ -public fun Array.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the array. - */ -public fun Array.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the array. - */ -public fun Array.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the array. - */ -public fun Array.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the array. - */ -public fun Array.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the array. - */ -public fun ByteArray.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the array. - */ -public fun ShortArray.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the array. - */ -public fun IntArray.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the array. - */ -public fun LongArray.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the array. - */ -public fun FloatArray.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the array. - */ -public fun DoubleArray.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - - -/** - * Returns the sum of all elements in the array. - */ -public fun Array.sum(): Int { - var sum: Int = 0 - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the array. - */ -public fun Array.sum(): Int { - var sum: Int = 0 - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the array. - */ -public fun Array.sum(): Int { - var sum: Int = 0 - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the array. - */ -public fun Array.sum(): Long { - var sum: Long = 0L - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the array. - */ -public fun Array.sum(): Float { - var sum: Float = 0.0f - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the array. - */ -public fun Array.sum(): Double { - var sum: Double = 0.0 - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the array. - */ -public fun ByteArray.sum(): Int { - var sum: Int = 0 - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the array. - */ -public fun ShortArray.sum(): Int { - var sum: Int = 0 - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the array. - */ -public fun IntArray.sum(): Int { - var sum: Int = 0 - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the array. - */ -public fun LongArray.sum(): Long { - var sum: Long = 0L - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the array. - */ -public fun FloatArray.sum(): Float { - var sum: Float = 0.0f - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the array. - */ -public fun DoubleArray.sum(): Double { - var sum: Double = 0.0 - for (element in this) { - sum += element - } - return sum -} - -// From _Arrays.kt. -/** - * Returns the range of valid indices for the array. - */ -public val Array.indices: IntRange - get() = IntRange(0, lastIndex) - -/** - * Returns the range of valid indices for the array. - */ -public val ByteArray.indices: IntRange - get() = IntRange(0, lastIndex) - -/** - * Returns the range of valid indices for the array. - */ -public val ShortArray.indices: IntRange - get() = IntRange(0, lastIndex) - -/** - * Returns the range of valid indices for the array. - */ -public val IntArray.indices: IntRange - get() = IntRange(0, lastIndex) - -/** - * Returns the range of valid indices for the array. - */ -public val LongArray.indices: IntRange - get() = IntRange(0, lastIndex) - -/** - * Returns the range of valid indices for the array. - */ -public val FloatArray.indices: IntRange - get() = IntRange(0, lastIndex) - -/** - * Returns the range of valid indices for the array. - */ -public val DoubleArray.indices: IntRange - get() = IntRange(0, lastIndex) - -/** - * Returns the range of valid indices for the array. - */ -public val BooleanArray.indices: IntRange - get() = IntRange(0, lastIndex) - -/** - * Returns the range of valid indices for the array. - */ -public val CharArray.indices: IntRange - get() = IntRange(0, lastIndex) - -/** - * Returns the last valid index for the array. - */ -public val Array.lastIndex: Int - get() = size - 1 - -/** - * Returns the last valid index for the array. - */ -public val ByteArray.lastIndex: Int - get() = size - 1 - -/** - * Returns the last valid index for the array. - */ -public val ShortArray.lastIndex: Int - get() = size - 1 - -/** - * Returns the last valid index for the array. - */ -public val IntArray.lastIndex: Int - get() = size - 1 - -/** - * Returns the last valid index for the array. - */ -public val LongArray.lastIndex: Int - get() = size - 1 - -/** - * Returns the last valid index for the array. - */ -public val FloatArray.lastIndex: Int - get() = size - 1 - -/** - * Returns the last valid index for the array. - */ -public val DoubleArray.lastIndex: Int - get() = size - 1 - -/** - * Returns the last valid index for the array. - */ -public val BooleanArray.lastIndex: Int - get() = size - 1 - -/** - * Returns the last valid index for the array. - */ -public val CharArray.lastIndex: Int - get() = size - 1 - -/** - * Returns `true` if the array is empty. - */ -@kotlin.internal.InlineOnly -public inline fun Array.isEmpty(): Boolean { - return size == 0 -} - -/** - * Returns `true` if the array is empty. - */ -@kotlin.internal.InlineOnly -public inline fun ByteArray.isEmpty(): Boolean { - return size == 0 -} - -/** - * Returns `true` if the array is empty. - */ -@kotlin.internal.InlineOnly -public inline fun ShortArray.isEmpty(): Boolean { - return size == 0 -} - -/** - * Returns `true` if the array is empty. - */ -@kotlin.internal.InlineOnly -public inline fun IntArray.isEmpty(): Boolean { - return size == 0 -} - -/** - * Returns `true` if the array is empty. - */ -@kotlin.internal.InlineOnly -public inline fun LongArray.isEmpty(): Boolean { - return size == 0 -} - -/** - * Returns `true` if the array is empty. - */ -@kotlin.internal.InlineOnly -public inline fun FloatArray.isEmpty(): Boolean { - return size == 0 -} - -/** - * Returns `true` if the array is empty. - */ -@kotlin.internal.InlineOnly -public inline fun DoubleArray.isEmpty(): Boolean { - return size == 0 -} -/** - * Returns `true` if the array is empty. - */ -@kotlin.internal.InlineOnly -public inline fun BooleanArray.isEmpty(): Boolean { - return size == 0 -} - -/** - * Returns `true` if the array is empty. - */ -@kotlin.internal.InlineOnly -public inline fun CharArray.isEmpty(): Boolean { - return size == 0 -} - -/** - * Returns `true` if the array is not empty. - */ -@kotlin.internal.InlineOnly -public inline fun Array.isNotEmpty(): Boolean { - return !isEmpty() -} - -/** - * Returns `true` if the array is not empty. - */ -@kotlin.internal.InlineOnly -public inline fun ByteArray.isNotEmpty(): Boolean { - return !isEmpty() -} - -/** - * Returns `true` if the array is not empty. - */ -@kotlin.internal.InlineOnly -public inline fun ShortArray.isNotEmpty(): Boolean { - return !isEmpty() -} - -/** - * Returns `true` if the array is not empty. - */ -@kotlin.internal.InlineOnly -public inline fun IntArray.isNotEmpty(): Boolean { - return !isEmpty() -} - -/** - * Returns `true` if the array is not empty. - */ -@kotlin.internal.InlineOnly -public inline fun LongArray.isNotEmpty(): Boolean { - return !isEmpty() -} - -/** - * Returns `true` if the array is not empty. - */ -@kotlin.internal.InlineOnly -public inline fun FloatArray.isNotEmpty(): Boolean { - return !isEmpty() -} - -/** - * Returns `true` if the array is not empty. - */ -@kotlin.internal.InlineOnly -public inline fun DoubleArray.isNotEmpty(): Boolean { - return !isEmpty() -} - -/** - * Returns `true` if the array is not empty. - */ -@kotlin.internal.InlineOnly -public inline fun BooleanArray.isNotEmpty(): Boolean { - return !isEmpty() -} - -/** - * Returns `true` if the array is not empty. - */ -@kotlin.internal.InlineOnly -public inline fun CharArray.isNotEmpty(): Boolean { - return !isEmpty() -} - -/** - * Returns last index of [element], or -1 if the array does not contain element. - */ -public fun <@kotlin.internal.OnlyInputTypes T> Array.lastIndexOf(element: T): Int { - if (element == null) { - for (index in indices.reversed()) { - if (this[index] == null) { - return index - } - } - } else { - for (index in indices.reversed()) { - if (element == this[index]) { - return index - } - } - } - return -1 -} - -/** - * Returns last index of [element], or -1 if the array does not contain element. - */ -public fun ByteArray.lastIndexOf(element: Byte): Int { - for (index in indices.reversed()) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns last index of [element], or -1 if the array does not contain element. - */ -public fun ShortArray.lastIndexOf(element: Short): Int { - for (index in indices.reversed()) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns last index of [element], or -1 if the array does not contain element. - */ -public fun IntArray.lastIndexOf(element: Int): Int { - for (index in indices.reversed()) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns last index of [element], or -1 if the array does not contain element. - */ -public fun LongArray.lastIndexOf(element: Long): Int { - for (index in indices.reversed()) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns last index of [element], or -1 if the array does not contain element. - */ -public fun FloatArray.lastIndexOf(element: Float): Int { - for (index in indices.reversed()) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns last index of [element], or -1 if the array does not contain element. - */ -public fun DoubleArray.lastIndexOf(element: Double): Int { - for (index in indices.reversed()) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns last index of [element], or -1 if the array does not contain element. - */ -public fun BooleanArray.lastIndexOf(element: Boolean): Int { - for (index in indices.reversed()) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Returns last index of [element], or -1 if the array does not contain element. - */ -public fun CharArray.lastIndexOf(element: Char): Int { - for (index in indices.reversed()) { - if (element == this[index]) { - return index - } - } - return -1 -} - -/** - * Appends all elements to the given [destination] collection. - */ -public fun > Array.toCollection(destination: C): C { - for (item in this) { - destination.add(item) - } - return destination -} - -/** - * Appends all elements to the given [destination] collection. - */ -public fun > ByteArray.toCollection(destination: C): C { - for (item in this) { - destination.add(item) - } - return destination -} - -/** - * Appends all elements to the given [destination] collection. - */ -public fun > ShortArray.toCollection(destination: C): C { - for (item in this) { - destination.add(item) - } - return destination -} - -/** - * Appends all elements to the given [destination] collection. - */ -public fun > IntArray.toCollection(destination: C): C { - for (item in this) { - destination.add(item) - } - return destination -} - -/** - * Appends all elements to the given [destination] collection. - */ -public fun > LongArray.toCollection(destination: C): C { - for (item in this) { - destination.add(item) - } - return destination -} - -/** - * Appends all elements to the given [destination] collection. - */ -public fun > FloatArray.toCollection(destination: C): C { - for (item in this) { - destination.add(item) - } - return destination -} - -/** - * Appends all elements to the given [destination] collection. - */ -public fun > DoubleArray.toCollection(destination: C): C { - for (item in this) { - destination.add(item) - } - return destination -} - -/** - * Appends all elements to the given [destination] collection. - */ -public fun > BooleanArray.toCollection(destination: C): C { - for (item in this) { - destination.add(item) - } - return destination -} - -/** - * Appends all elements to the given [destination] collection. - */ -public fun > CharArray.toCollection(destination: C): C { - for (item in this) { - destination.add(item) - } - return destination -} - -/** - * Returns a [List] containing all elements. - */ -public fun Array.toList(): List { - return when (size) { - 0 -> emptyList() - 1 -> listOf(this[0]) - else -> this.toMutableList() - } -} - -/** - * Returns a [List] containing all elements. - */ -public fun ByteArray.toList(): List { - return when (size) { - 0 -> emptyList() - 1 -> listOf(this[0]) - else -> this.toMutableList() - } -} - -/** - * Returns a [List] containing all elements. - */ -public fun ShortArray.toList(): List { - return when (size) { - 0 -> emptyList() - 1 -> listOf(this[0]) - else -> this.toMutableList() - } -} - -/** - * Returns a [List] containing all elements. - */ -public fun IntArray.toList(): List { - return when (size) { - 0 -> emptyList() - 1 -> listOf(this[0]) - else -> this.toMutableList() - } -} - -/** - * Returns a [List] containing all elements. - */ -public fun LongArray.toList(): List { - return when (size) { - 0 -> emptyList() - 1 -> listOf(this[0]) - else -> this.toMutableList() - } -} - -/** - * Returns a [List] containing all elements. - */ -public fun FloatArray.toList(): List { - return when (size) { - 0 -> emptyList() - 1 -> listOf(this[0]) - else -> this.toMutableList() - } -} - -/** - * Returns a [List] containing all elements. - */ -public fun DoubleArray.toList(): List { - return when (size) { - 0 -> emptyList() - 1 -> listOf(this[0]) - else -> this.toMutableList() - } -} - -/** - * Returns a [List] containing all elements. - */ -public fun BooleanArray.toList(): List { - return when (size) { - 0 -> emptyList() - 1 -> listOf(this[0]) - else -> this.toMutableList() - } -} - -/** - * Returns a [List] containing all elements. - */ -public fun CharArray.toList(): List { - return when (size) { - 0 -> emptyList() - 1 -> listOf(this[0]) - else -> this.toMutableList() - } -} - - -/** - * Returns a [MutableList] filled with all elements of this array. - */ -public fun Array.toMutableList(): MutableList { - return ArrayList(this.asCollection()) -} - - -/** - * Returns a [MutableList] filled with all elements of this array. - */ -public fun ByteArray.toMutableList(): MutableList { - val list = ArrayList(size) - for (item in this) list.add(item) - return list -} - -/** - * Returns a [MutableList] filled with all elements of this array. - */ -public fun ShortArray.toMutableList(): MutableList { - val list = ArrayList(size) - for (item in this) list.add(item) - return list -} - -/** - * Returns a [MutableList] filled with all elements of this array. - */ -public fun IntArray.toMutableList(): MutableList { - val list = ArrayList(size) - for (item in this) list.add(item) - return list -} - -/** - * Returns a [MutableList] filled with all elements of this array. - */ -public fun LongArray.toMutableList(): MutableList { - val list = ArrayList(size) - for (item in this) list.add(item) - return list -} - -/** - * Returns a [MutableList] filled with all elements of this array. - */ -public fun FloatArray.toMutableList(): MutableList { - val list = ArrayList(size) - for (item in this) list.add(item) - return list -} - -/** - * Returns a [MutableList] filled with all elements of this array. - */ -public fun DoubleArray.toMutableList(): MutableList { - val list = ArrayList(size) - for (item in this) list.add(item) - return list -} - -/** - * Returns a [MutableList] filled with all elements of this array. - */ -public fun BooleanArray.toMutableList(): MutableList { - val list = ArrayList(size) - for (item in this) list.add(item) - return list -} - -/** - * Returns a [MutableList] filled with all elements of this array. - */ -public fun CharArray.toMutableList(): MutableList { - val list = ArrayList(size) - for (item in this) list.add(item) - return list -} - -/** - * Returns a [HashSet] of all elements. - */ -public fun Array.toHashSet(): HashSet { - return toCollection(HashSet(mapCapacity(size))) -} - -/** - * Returns a [HashSet] of all elements. - */ -public fun ByteArray.toHashSet(): HashSet { - return toCollection(HashSet(mapCapacity(size))) -} - -/** - * Returns a [HashSet] of all elements. - */ -public fun ShortArray.toHashSet(): HashSet { - return toCollection(HashSet(mapCapacity(size))) -} - -/** - * Returns a [HashSet] of all elements. - */ -public fun IntArray.toHashSet(): HashSet { - return toCollection(HashSet(mapCapacity(size))) -} - -/** - * Returns a [HashSet] of all elements. - */ -public fun LongArray.toHashSet(): HashSet { - return toCollection(HashSet(mapCapacity(size))) -} - -/** - * Returns a [HashSet] of all elements. - */ -public fun FloatArray.toHashSet(): HashSet { - return toCollection(HashSet(mapCapacity(size))) -} - -/** - * Returns a [HashSet] of all elements. - */ -public fun DoubleArray.toHashSet(): HashSet { - return toCollection(HashSet(mapCapacity(size))) -} - -/** - * Returns a [HashSet] of all elements. - */ -public fun BooleanArray.toHashSet(): HashSet { - return toCollection(HashSet(mapCapacity(size))) -} - -/** - * Returns a [HashSet] of all elements. - */ -public fun CharArray.toHashSet(): HashSet { - return toCollection(HashSet(mapCapacity(size))) -} - -/** - * Returns a [Set] of all elements. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun Array.toSet(): Set { - return when (size) { - 0 -> emptySet() - 1 -> setOf(this[0]) - else -> toCollection(LinkedHashSet(mapCapacity(size))) - } -} - -/** - * Returns a [Set] of all elements. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun ByteArray.toSet(): Set { - return when (size) { - 0 -> emptySet() - 1 -> setOf(this[0]) - else -> toCollection(LinkedHashSet(mapCapacity(size))) - } -} - -/** - * Returns a [Set] of all elements. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun ShortArray.toSet(): Set { - return when (size) { - 0 -> emptySet() - 1 -> setOf(this[0]) - else -> toCollection(LinkedHashSet(mapCapacity(size))) - } -} - -/** - * Returns a [Set] of all elements. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun IntArray.toSet(): Set { - return when (size) { - 0 -> emptySet() - 1 -> setOf(this[0]) - else -> toCollection(LinkedHashSet(mapCapacity(size))) - } -} - -/** - * Returns a [Set] of all elements. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun LongArray.toSet(): Set { - return when (size) { - 0 -> emptySet() - 1 -> setOf(this[0]) - else -> toCollection(LinkedHashSet(mapCapacity(size))) - } -} - -/** - * Returns a [Set] of all elements. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun FloatArray.toSet(): Set { - return when (size) { - 0 -> emptySet() - 1 -> setOf(this[0]) - else -> toCollection(LinkedHashSet(mapCapacity(size))) - } -} - -/** - * Returns a [Set] of all elements. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun DoubleArray.toSet(): Set { - return when (size) { - 0 -> emptySet() - 1 -> setOf(this[0]) - else -> toCollection(LinkedHashSet(mapCapacity(size))) - } -} - -/** - * Returns a [Set] of all elements. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun BooleanArray.toSet(): Set { - return when (size) { - 0 -> emptySet() - 1 -> setOf(this[0]) - else -> toCollection(LinkedHashSet(mapCapacity(size))) - } -} - -/** - * Returns a [Set] of all elements. - * - * The returned set preserves the element iteration order of the original array. - */ -public fun CharArray.toSet(): Set { - return when (size) { - 0 -> emptySet() - 1 -> setOf(this[0]) - else -> toCollection(LinkedHashSet(mapCapacity(size))) - } -} - -/** - * Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. - */ -public inline fun Array.flatMap(transform: (T) -> Iterable): List { - return flatMapTo(ArrayList(), transform) -} - -/** - * Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. - */ -public inline fun ByteArray.flatMap(transform: (Byte) -> Iterable): List { - return flatMapTo(ArrayList(), transform) -} - -/** - * Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. - */ -public inline fun ShortArray.flatMap(transform: (Short) -> Iterable): List { - return flatMapTo(ArrayList(), transform) -} - -/** - * Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. - */ -public inline fun IntArray.flatMap(transform: (Int) -> Iterable): List { - return flatMapTo(ArrayList(), transform) -} - -/** - * Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. - */ -public inline fun LongArray.flatMap(transform: (Long) -> Iterable): List { - return flatMapTo(ArrayList(), transform) -} - -/** - * Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. - */ -public inline fun FloatArray.flatMap(transform: (Float) -> Iterable): List { - return flatMapTo(ArrayList(), transform) -} - -/** - * Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. - */ -public inline fun DoubleArray.flatMap(transform: (Double) -> Iterable): List { - return flatMapTo(ArrayList(), transform) -} - -/** - * Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. - */ -public inline fun BooleanArray.flatMap(transform: (Boolean) -> Iterable): List { - return flatMapTo(ArrayList(), transform) -} - -/** - * Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original array. - */ -public inline fun CharArray.flatMap(transform: (Char) -> Iterable): List { - return flatMapTo(ArrayList(), transform) -} - -/** - * Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. - */ -public inline fun > Array.flatMapTo(destination: C, transform: (T) -> Iterable): C { - for (element in this) { - val list = transform(element) - destination.addAll(list) - } - return destination -} - -/** - * Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. - */ -public inline fun > ByteArray.flatMapTo(destination: C, transform: (Byte) -> Iterable): C { - for (element in this) { - val list = transform(element) - destination.addAll(list) - } - return destination -} - -/** - * Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. - */ -public inline fun > ShortArray.flatMapTo(destination: C, transform: (Short) -> Iterable): C { - for (element in this) { - val list = transform(element) - destination.addAll(list) - } - return destination -} - -/** - * Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. - */ -public inline fun > IntArray.flatMapTo(destination: C, transform: (Int) -> Iterable): C { - for (element in this) { - val list = transform(element) - destination.addAll(list) - } - return destination -} - -/** - * Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. - */ -public inline fun > LongArray.flatMapTo(destination: C, transform: (Long) -> Iterable): C { - for (element in this) { - val list = transform(element) - destination.addAll(list) - } - return destination -} - -/** - * Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. - */ -public inline fun > FloatArray.flatMapTo(destination: C, transform: (Float) -> Iterable): C { - for (element in this) { - val list = transform(element) - destination.addAll(list) - } - return destination -} - -/** - * Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. - */ -public inline fun > DoubleArray.flatMapTo(destination: C, transform: (Double) -> Iterable): C { - for (element in this) { - val list = transform(element) - destination.addAll(list) - } - return destination -} - -/** - * Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. - */ -public inline fun > BooleanArray.flatMapTo(destination: C, transform: (Boolean) -> Iterable): C { - for (element in this) { - val list = transform(element) - destination.addAll(list) - } - return destination -} - -/** - * Appends all elements yielded from results of [transform] function being invoked on each element of original array, to the given [destination]. - */ -public inline fun > CharArray.flatMapTo(destination: C, transform: (Char) -> Iterable): C { - for (element in this) { - val list = transform(element) - destination.addAll(list) - } - return destination -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and returns a map where each group key is associated with a list of corresponding elements. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun Array.groupBy(keySelector: (T) -> K): Map> { - return groupByTo(LinkedHashMap>(), keySelector) -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and returns a map where each group key is associated with a list of corresponding elements. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun ByteArray.groupBy(keySelector: (Byte) -> K): Map> { - return groupByTo(LinkedHashMap>(), keySelector) -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and returns a map where each group key is associated with a list of corresponding elements. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun ShortArray.groupBy(keySelector: (Short) -> K): Map> { - return groupByTo(LinkedHashMap>(), keySelector) -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and returns a map where each group key is associated with a list of corresponding elements. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun IntArray.groupBy(keySelector: (Int) -> K): Map> { - return groupByTo(LinkedHashMap>(), keySelector) -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and returns a map where each group key is associated with a list of corresponding elements. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun LongArray.groupBy(keySelector: (Long) -> K): Map> { - return groupByTo(LinkedHashMap>(), keySelector) -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and returns a map where each group key is associated with a list of corresponding elements. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun FloatArray.groupBy(keySelector: (Float) -> K): Map> { - return groupByTo(LinkedHashMap>(), keySelector) -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and returns a map where each group key is associated with a list of corresponding elements. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun DoubleArray.groupBy(keySelector: (Double) -> K): Map> { - return groupByTo(LinkedHashMap>(), keySelector) -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and returns a map where each group key is associated with a list of corresponding elements. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun BooleanArray.groupBy(keySelector: (Boolean) -> K): Map> { - return groupByTo(LinkedHashMap>(), keySelector) -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and returns a map where each group key is associated with a list of corresponding elements. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun CharArray.groupBy(keySelector: (Char) -> K): Map> { - return groupByTo(LinkedHashMap>(), keySelector) -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and returns a map where each group key is associated with a list of corresponding values. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun Array.groupBy(keySelector: (T) -> K, valueTransform: (T) -> V): Map> { - return groupByTo(LinkedHashMap>(), keySelector, valueTransform) -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and returns a map where each group key is associated with a list of corresponding values. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun ByteArray.groupBy(keySelector: (Byte) -> K, valueTransform: (Byte) -> V): Map> { - return groupByTo(LinkedHashMap>(), keySelector, valueTransform) -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and returns a map where each group key is associated with a list of corresponding values. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun ShortArray.groupBy(keySelector: (Short) -> K, valueTransform: (Short) -> V): Map> { - return groupByTo(LinkedHashMap>(), keySelector, valueTransform) -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and returns a map where each group key is associated with a list of corresponding values. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun IntArray.groupBy(keySelector: (Int) -> K, valueTransform: (Int) -> V): Map> { - return groupByTo(LinkedHashMap>(), keySelector, valueTransform) -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and returns a map where each group key is associated with a list of corresponding values. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun LongArray.groupBy(keySelector: (Long) -> K, valueTransform: (Long) -> V): Map> { - return groupByTo(LinkedHashMap>(), keySelector, valueTransform) -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and returns a map where each group key is associated with a list of corresponding values. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun FloatArray.groupBy(keySelector: (Float) -> K, valueTransform: (Float) -> V): Map> { - return groupByTo(LinkedHashMap>(), keySelector, valueTransform) -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and returns a map where each group key is associated with a list of corresponding values. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun DoubleArray.groupBy(keySelector: (Double) -> K, valueTransform: (Double) -> V): Map> { - return groupByTo(LinkedHashMap>(), keySelector, valueTransform) -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and returns a map where each group key is associated with a list of corresponding values. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun BooleanArray.groupBy(keySelector: (Boolean) -> K, valueTransform: (Boolean) -> V): Map> { - return groupByTo(LinkedHashMap>(), keySelector, valueTransform) -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and returns a map where each group key is associated with a list of corresponding values. - * - * The returned map preserves the entry iteration order of the keys produced from the original array. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun CharArray.groupBy(keySelector: (Char) -> K, valueTransform: (Char) -> V): Map> { - return groupByTo(LinkedHashMap>(), keySelector, valueTransform) -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and puts to the [destination] map each group key associated with a list of corresponding elements. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun >> Array.groupByTo(destination: M, keySelector: (T) -> K): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(element) - } - return destination -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and puts to the [destination] map each group key associated with a list of corresponding elements. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun >> ByteArray.groupByTo(destination: M, keySelector: (Byte) -> K): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(element) - } - return destination -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and puts to the [destination] map each group key associated with a list of corresponding elements. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun >> ShortArray.groupByTo(destination: M, keySelector: (Short) -> K): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(element) - } - return destination -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and puts to the [destination] map each group key associated with a list of corresponding elements. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun >> IntArray.groupByTo(destination: M, keySelector: (Int) -> K): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(element) - } - return destination -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and puts to the [destination] map each group key associated with a list of corresponding elements. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun >> LongArray.groupByTo(destination: M, keySelector: (Long) -> K): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(element) - } - return destination -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and puts to the [destination] map each group key associated with a list of corresponding elements. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun >> FloatArray.groupByTo(destination: M, keySelector: (Float) -> K): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(element) - } - return destination -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and puts to the [destination] map each group key associated with a list of corresponding elements. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun >> DoubleArray.groupByTo(destination: M, keySelector: (Double) -> K): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(element) - } - return destination -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and puts to the [destination] map each group key associated with a list of corresponding elements. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun >> BooleanArray.groupByTo(destination: M, keySelector: (Boolean) -> K): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(element) - } - return destination -} - -/** - * Groups elements of the original array by the key returned by the given [keySelector] function - * applied to each element and puts to the [destination] map each group key associated with a list of corresponding elements. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun >> CharArray.groupByTo(destination: M, keySelector: (Char) -> K): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(element) - } - return destination -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and puts to the [destination] map each group key associated with a list of corresponding values. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun >> Array.groupByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(valueTransform(element)) - } - return destination -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and puts to the [destination] map each group key associated with a list of corresponding values. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun >> ByteArray.groupByTo(destination: M, keySelector: (Byte) -> K, valueTransform: (Byte) -> V): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(valueTransform(element)) - } - return destination -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and puts to the [destination] map each group key associated with a list of corresponding values. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun >> ShortArray.groupByTo(destination: M, keySelector: (Short) -> K, valueTransform: (Short) -> V): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(valueTransform(element)) - } - return destination -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and puts to the [destination] map each group key associated with a list of corresponding values. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun >> IntArray.groupByTo(destination: M, keySelector: (Int) -> K, valueTransform: (Int) -> V): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(valueTransform(element)) - } - return destination -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and puts to the [destination] map each group key associated with a list of corresponding values. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun >> LongArray.groupByTo(destination: M, keySelector: (Long) -> K, valueTransform: (Long) -> V): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(valueTransform(element)) - } - return destination -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and puts to the [destination] map each group key associated with a list of corresponding values. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun >> FloatArray.groupByTo(destination: M, keySelector: (Float) -> K, valueTransform: (Float) -> V): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(valueTransform(element)) - } - return destination -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and puts to the [destination] map each group key associated with a list of corresponding values. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun >> DoubleArray.groupByTo(destination: M, keySelector: (Double) -> K, valueTransform: (Double) -> V): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(valueTransform(element)) - } - return destination -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and puts to the [destination] map each group key associated with a list of corresponding values. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun >> BooleanArray.groupByTo(destination: M, keySelector: (Boolean) -> K, valueTransform: (Boolean) -> V): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(valueTransform(element)) - } - return destination -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original array - * by the key returned by the given [keySelector] function applied to the element - * and puts to the [destination] map each group key associated with a list of corresponding values. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun >> CharArray.groupByTo(destination: M, keySelector: (Char) -> K, valueTransform: (Char) -> V): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(valueTransform(element)) - } - return destination -} - -/** - * Creates a [Grouping] source from an array to be used later with one of group-and-fold operations - * using the specified [keySelector] function to extract a key from each element. - * - * @sample samples.collections.Collections.Transformations.groupingByEachCount - */ -@SinceKotlin("1.1") -public inline fun Array.groupingBy(crossinline keySelector: (T) -> K): Grouping { - return object : Grouping { - override fun sourceIterator(): Iterator = this@groupingBy.iterator() - override fun keyOf(element: T): K = keySelector(element) - } -} - -/** - * Returns new array which is a copy of the original array. - */ -@kotlin.internal.InlineOnly -public inline fun Array.copyOf(): Array { - return this.copyOfUninitializedElements(size) -} - -/** - * Returns new array which is a copy of the original array. - */ -@kotlin.internal.InlineOnly -public inline fun ByteArray.copyOf(): ByteArray { - return copyOfUninitializedElements(size) -} - -/** - * Returns new array which is a copy of the original array. - */ -@kotlin.internal.InlineOnly -public inline fun ShortArray.copyOf(): ShortArray { - return copyOfUninitializedElements(size) -} - -/** - * Returns new array which is a copy of the original array. - */ -@kotlin.internal.InlineOnly -public inline fun IntArray.copyOf(): IntArray { - return copyOfUninitializedElements(size) -} - -/** - * Returns new array which is a copy of the original array. - */ -@kotlin.internal.InlineOnly -public inline fun LongArray.copyOf(): LongArray { - return copyOfUninitializedElements(size) -} - -/** - * Returns new array which is a copy of the original array. - */ -@kotlin.internal.InlineOnly -public inline fun FloatArray.copyOf(): FloatArray { - return copyOfUninitializedElements(size) -} - -/** - * Returns new array which is a copy of the original array. - */ -@kotlin.internal.InlineOnly -public inline fun DoubleArray.copyOf(): DoubleArray { - return copyOfUninitializedElements(size) -} - -/** - * Returns new array which is a copy of the original array. - */ -@kotlin.internal.InlineOnly -public inline fun BooleanArray.copyOf(): BooleanArray { - return copyOfUninitializedElements(size) -} - -/** - * Returns new array which is a copy of the original array. - */ -@kotlin.internal.InlineOnly -public inline fun CharArray.copyOf(): CharArray { - return copyOfUninitializedElements(size) -} - -/** - * Returns new array which is a copy of the original array, resized to the given [newSize]. - */ -@kotlin.internal.InlineOnly -public inline fun Array.copyOf(newSize: Int): Array { - return copyOfNulls(newSize) -} - -/** - * Returns new array which is a copy of the original array, resized to the given [newSize]. - */ -@kotlin.internal.InlineOnly -public inline fun ByteArray.copyOf(newSize: Int): ByteArray { - return copyOfUninitializedElements(newSize) -} - -/** - * Returns new array which is a copy of the original array, resized to the given [newSize]. - */ -@kotlin.internal.InlineOnly -public inline fun ShortArray.copyOf(newSize: Int): ShortArray { - return copyOfUninitializedElements(newSize) -} - -/** - * Returns new array which is a copy of the original array, resized to the given [newSize]. - */ -@kotlin.internal.InlineOnly -public inline fun IntArray.copyOf(newSize: Int): IntArray { - return copyOfUninitializedElements(newSize) -} - -/** - * Returns new array which is a copy of the original array, resized to the given [newSize]. - */ -@kotlin.internal.InlineOnly -public inline fun LongArray.copyOf(newSize: Int): LongArray { - return copyOfUninitializedElements(newSize) -} - -/** - * Returns new array which is a copy of the original array, resized to the given [newSize]. - */ -@kotlin.internal.InlineOnly -public inline fun FloatArray.copyOf(newSize: Int): FloatArray { - return copyOfUninitializedElements(newSize) -} - -/** - * Returns new array which is a copy of the original array, resized to the given [newSize]. - */ -@kotlin.internal.InlineOnly -public inline fun DoubleArray.copyOf(newSize: Int): DoubleArray { - return copyOfUninitializedElements(newSize) -} - -/** - * Returns new array which is a copy of the original array, resized to the given [newSize]. - */ -@kotlin.internal.InlineOnly -public inline fun BooleanArray.copyOf(newSize: Int): BooleanArray { - return copyOfUninitializedElements(newSize) -} - -/** - * Returns new array which is a copy of the original array, resized to the given [newSize]. - */ -@kotlin.internal.InlineOnly -public inline fun CharArray.copyOf(newSize: Int): CharArray { - return copyOfUninitializedElements(newSize) -} - -/** - * Returns new array which is a copy of range of original array. - */ -// TODO: The method may check input or return Array. -// Now we check its input (fromIndex <= toIndex < size). -// Sync its behaviour wiht Kotlin JVM when the problem is solved there. -@kotlin.internal.InlineOnly -public inline fun Array.copyOfRange(fromIndex: Int, toIndex: Int): Array { - if (fromIndex > toIndex || toIndex > size) - throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") - return copyOfUninitializedElements(fromIndex, toIndex) -} - -/** - * Returns new array which is a copy of range of original array. - */ -@kotlin.internal.InlineOnly -public inline fun ByteArray.copyOfRange(fromIndex: Int, toIndex: Int): ByteArray { - if (fromIndex > toIndex || toIndex > size) - throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") - return copyOfUninitializedElements(fromIndex, toIndex) -} - -/** - * Returns new array which is a copy of range of original array. - */ -@kotlin.internal.InlineOnly -public inline fun ShortArray.copyOfRange(fromIndex: Int, toIndex: Int): ShortArray { - if (fromIndex > toIndex || toIndex > size) - throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") - return copyOfUninitializedElements(fromIndex, toIndex) -} - -/** - * Returns new array which is a copy of range of original array. - */ -@kotlin.internal.InlineOnly -public inline fun IntArray.copyOfRange(fromIndex: Int, toIndex: Int): IntArray { - if (fromIndex > toIndex || toIndex > size) - throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") - return copyOfUninitializedElements(fromIndex, toIndex) -} - -/** - * Returns new array which is a copy of range of original array. - */ -@kotlin.internal.InlineOnly -public inline fun LongArray.copyOfRange(fromIndex: Int, toIndex: Int): LongArray { - if (fromIndex > toIndex || toIndex > size) - throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") - return copyOfUninitializedElements(fromIndex, toIndex) -} - -/** - * Returns new array which is a copy of range of original array. - */ -@kotlin.internal.InlineOnly -public inline fun FloatArray.copyOfRange(fromIndex: Int, toIndex: Int): FloatArray { - if (fromIndex > toIndex || toIndex > size) - throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") - return copyOfUninitializedElements(fromIndex, toIndex) -} - -/** - * Returns new array which is a copy of range of original array. - */ -@kotlin.internal.InlineOnly -public inline fun DoubleArray.copyOfRange(fromIndex: Int, toIndex: Int): DoubleArray { - if (fromIndex > toIndex || toIndex > size) - throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") - return copyOfUninitializedElements(fromIndex, toIndex) -} - -/** - * Returns new array which is a copy of range of original array. - */ -@kotlin.internal.InlineOnly -public inline fun BooleanArray.copyOfRange(fromIndex: Int, toIndex: Int): BooleanArray { - if (fromIndex > toIndex || toIndex > size) - throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") - return copyOfUninitializedElements(fromIndex, toIndex) -} - -/** - * Returns new array which is a copy of range of original array. - */ -@kotlin.internal.InlineOnly -public inline fun CharArray.copyOfRange(fromIndex: Int, toIndex: Int): CharArray { - if (fromIndex > toIndex || toIndex > size) - throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") - return copyOfUninitializedElements(fromIndex, toIndex) -} - - -/** - * Sorts the array in-place according to the order specified by the given [comparator]. - */ -public fun Array.sortWith(comparator: Comparator): Unit { - if (size > 1) sortArrayWith(this, 0, size, comparator) -} - -/** - * Sorts elements in the array in-place according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > Array.sortBy(crossinline selector: (T) -> R?): Unit { - if (size > 1) sortWith(compareBy(selector)) -} - -/** - * Sorts elements in the array in-place descending according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > Array.sortByDescending(crossinline selector: (T) -> R?): Unit { - if (size > 1) sortWith(compareByDescending(selector)) -} - -/** - * Sorts elements in the array in-place descending according to their natural sort order. - */ -public fun > Array.sortDescending(): Unit { - sortWith(reverseOrder()) -} - -/** - * Sorts elements in the array in-place descending according to their natural sort order. - */ -public fun ByteArray.sortDescending(): Unit { - if (size > 1) { - sort() - reverse() - } -} - -/** - * Sorts elements in the array in-place descending according to their natural sort order. - */ -public fun ShortArray.sortDescending(): Unit { - if (size > 1) { - sort() - reverse() - } -} - -/** - * Sorts elements in the array in-place descending according to their natural sort order. - */ -public fun IntArray.sortDescending(): Unit { - if (size > 1) { - sort() - reverse() - } -} - -/** - * Sorts elements in the array in-place descending according to their natural sort order. - */ -public fun LongArray.sortDescending(): Unit { - if (size > 1) { - sort() - reverse() - } -} - -/** - * Sorts elements in the array in-place descending according to their natural sort order. - */ -public fun FloatArray.sortDescending(): Unit { - if (size > 1) { - sort() - reverse() - } -} - -/** - * Sorts elements in the array in-place descending according to their natural sort order. - */ -public fun DoubleArray.sortDescending(): Unit { - if (size > 1) { - sort() - reverse() - } -} - -/** - * Sorts elements in the array in-place descending according to their natural sort order. - */ -public fun CharArray.sortDescending(): Unit { - if (size > 1) { - sort() - reverse() - } -} - -/** - * Returns a list of all elements sorted according to their natural sort order. - */ -public fun > Array.sorted(): List { - return sortedArray().asList() -} - -/** - * Returns a list of all elements sorted according to their natural sort order. - */ -public fun ByteArray.sorted(): List { - return toTypedArray().apply { sort() }.asList() -} - -/** - * Returns a list of all elements sorted according to their natural sort order. - */ -public fun ShortArray.sorted(): List { - return toTypedArray().apply { sort() }.asList() -} - -/** - * Returns a list of all elements sorted according to their natural sort order. - */ -public fun IntArray.sorted(): List { - return toTypedArray().apply { sort() }.asList() -} - -/** - * Returns a list of all elements sorted according to their natural sort order. - */ -public fun LongArray.sorted(): List { - return toTypedArray().apply { sort() }.asList() -} - -/** - * Returns a list of all elements sorted according to their natural sort order. - */ -public fun FloatArray.sorted(): List { - return toTypedArray().apply { sort() }.asList() -} - -/** - * Returns a list of all elements sorted according to their natural sort order. - */ -public fun DoubleArray.sorted(): List { - return toTypedArray().apply { sort() }.asList() -} - -/** - * Returns a list of all elements sorted according to their natural sort order. - */ -public fun CharArray.sorted(): List { - return toTypedArray().apply { sort() }.asList() -} - -/** - * Returns an array with all elements of this array sorted according to their natural sort order. - */ -public fun > Array.sortedArray(): Array { - if (isEmpty()) return this - return this.copyOf().apply { sort() } -} - -/** - * Returns an array with all elements of this array sorted according to their natural sort order. - */ -public fun ByteArray.sortedArray(): ByteArray { - if (isEmpty()) return this - return this.copyOf().apply { sort() } -} - -/** - * Returns an array with all elements of this array sorted according to their natural sort order. - */ -public fun ShortArray.sortedArray(): ShortArray { - if (isEmpty()) return this - return this.copyOf().apply { sort() } -} - -/** - * Returns an array with all elements of this array sorted according to their natural sort order. - */ -public fun IntArray.sortedArray(): IntArray { - if (isEmpty()) return this - return this.copyOf().apply { sort() } -} - -/** - * Returns an array with all elements of this array sorted according to their natural sort order. - */ -public fun LongArray.sortedArray(): LongArray { - if (isEmpty()) return this - return this.copyOf().apply { sort() } -} - -/** - * Returns an array with all elements of this array sorted according to their natural sort order. - */ -public fun FloatArray.sortedArray(): FloatArray { - if (isEmpty()) return this - return this.copyOf().apply { sort() } -} - -/** - * Returns an array with all elements of this array sorted according to their natural sort order. - */ -public fun DoubleArray.sortedArray(): DoubleArray { - if (isEmpty()) return this - return this.copyOf().apply { sort() } -} - -/** - * Returns an array with all elements of this array sorted according to their natural sort order. - */ -public fun CharArray.sortedArray(): CharArray { - if (isEmpty()) return this - return this.copyOf().apply { sort() } -} - -/** - * Returns an array with all elements of this array sorted descending according to their natural sort order. - */ -public fun > Array.sortedArrayDescending(): Array { - if (isEmpty()) return this - return this.copyOf().apply { sortWith(reverseOrder()) } -} - -/** - * Returns an array with all elements of this array sorted descending according to their natural sort order. - */ -public fun ByteArray.sortedArrayDescending(): ByteArray { - if (isEmpty()) return this - return this.copyOf().apply { sortDescending() } -} - -/** - * Returns an array with all elements of this array sorted descending according to their natural sort order. - */ -public fun ShortArray.sortedArrayDescending(): ShortArray { - if (isEmpty()) return this - return this.copyOf().apply { sortDescending() } -} - -/** - * Returns an array with all elements of this array sorted descending according to their natural sort order. - */ -public fun IntArray.sortedArrayDescending(): IntArray { - if (isEmpty()) return this - return this.copyOf().apply { sortDescending() } -} - -/** - * Returns an array with all elements of this array sorted descending according to their natural sort order. - */ -public fun LongArray.sortedArrayDescending(): LongArray { - if (isEmpty()) return this - return this.copyOf().apply { sortDescending() } -} - -/** - * Returns an array with all elements of this array sorted descending according to their natural sort order. - */ -public fun FloatArray.sortedArrayDescending(): FloatArray { - if (isEmpty()) return this - return this.copyOf().apply { sortDescending() } -} - -/** - * Returns an array with all elements of this array sorted descending according to their natural sort order. - */ -public fun DoubleArray.sortedArrayDescending(): DoubleArray { - if (isEmpty()) return this - return this.copyOf().apply { sortDescending() } -} - -/** - * Returns an array with all elements of this array sorted descending according to their natural sort order. - */ -public fun CharArray.sortedArrayDescending(): CharArray { - if (isEmpty()) return this - return this.copyOf().apply { sortDescending() } -} - -/** - * Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > Array.sortedBy(crossinline selector: (T) -> R?): List { - return sortedWith(compareBy(selector)) -} - -/** - * Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > ByteArray.sortedBy(crossinline selector: (Byte) -> R?): List { - return sortedWith(compareBy(selector)) -} - -/** - * Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > ShortArray.sortedBy(crossinline selector: (Short) -> R?): List { - return sortedWith(compareBy(selector)) -} - -/** - * Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > IntArray.sortedBy(crossinline selector: (Int) -> R?): List { - return sortedWith(compareBy(selector)) -} - -/** - * Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > LongArray.sortedBy(crossinline selector: (Long) -> R?): List { - return sortedWith(compareBy(selector)) -} - -/** - * Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > FloatArray.sortedBy(crossinline selector: (Float) -> R?): List { - return sortedWith(compareBy(selector)) -} - -/** - * Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > DoubleArray.sortedBy(crossinline selector: (Double) -> R?): List { - return sortedWith(compareBy(selector)) -} - -/** - * Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > BooleanArray.sortedBy(crossinline selector: (Boolean) -> R?): List { - return sortedWith(compareBy(selector)) -} - -/** - * Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > CharArray.sortedBy(crossinline selector: (Char) -> R?): List { - return sortedWith(compareBy(selector)) -} - -/** - * Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > Array.sortedByDescending(crossinline selector: (T) -> R?): List { - return sortedWith(compareByDescending(selector)) -} - -/** - * Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > ByteArray.sortedByDescending(crossinline selector: (Byte) -> R?): List { - return sortedWith(compareByDescending(selector)) -} - -/** - * Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > ShortArray.sortedByDescending(crossinline selector: (Short) -> R?): List { - return sortedWith(compareByDescending(selector)) -} - -/** - * Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > IntArray.sortedByDescending(crossinline selector: (Int) -> R?): List { - return sortedWith(compareByDescending(selector)) -} - -/** - * Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > LongArray.sortedByDescending(crossinline selector: (Long) -> R?): List { - return sortedWith(compareByDescending(selector)) -} - -/** - * Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > FloatArray.sortedByDescending(crossinline selector: (Float) -> R?): List { - return sortedWith(compareByDescending(selector)) -} - -/** - * Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > DoubleArray.sortedByDescending(crossinline selector: (Double) -> R?): List { - return sortedWith(compareByDescending(selector)) -} - -/** - * Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > BooleanArray.sortedByDescending(crossinline selector: (Boolean) -> R?): List { - return sortedWith(compareByDescending(selector)) -} - -/** - * Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > CharArray.sortedByDescending(crossinline selector: (Char) -> R?): List { - return sortedWith(compareByDescending(selector)) -} - -/** - * Returns a list of all elements sorted descending according to their natural sort order. - */ -public fun > Array.sortedDescending(): List { - return sortedWith(reverseOrder()) -} - -/** - * Returns a list of all elements sorted descending according to their natural sort order. - */ -public fun ByteArray.sortedDescending(): List { - return copyOf().apply { sort() }.reversed() -} - -/** - * Returns a list of all elements sorted descending according to their natural sort order. - */ -public fun ShortArray.sortedDescending(): List { - return copyOf().apply { sort() }.reversed() -} - -/** - * Returns a list of all elements sorted descending according to their natural sort order. - */ -public fun IntArray.sortedDescending(): List { - return copyOf().apply { sort() }.reversed() -} - -/** - * Returns a list of all elements sorted descending according to their natural sort order. - */ -public fun LongArray.sortedDescending(): List { - return copyOf().apply { sort() }.reversed() -} - -/** - * Returns a list of all elements sorted descending according to their natural sort order. - */ -public fun FloatArray.sortedDescending(): List { - return copyOf().apply { sort() }.reversed() -} - -/** - * Returns a list of all elements sorted descending according to their natural sort order. - */ -public fun DoubleArray.sortedDescending(): List { - return copyOf().apply { sort() }.reversed() -} - -/** - * Returns a list of all elements sorted descending according to their natural sort order. - */ -public fun CharArray.sortedDescending(): List { - return copyOf().apply { sort() }.reversed() -} - -/** - * Sorts the array in-place according to the natural order of its elements. - * - * @throws ClassCastException if any element of the array is not [Comparable]. - */ -public fun Array.sort(): Unit { - if (size > 1) sortArrayComparable(this) -} - -public fun Array.sortWith(comparator: Comparator, fromIndex: Int = 0, toIndex: Int = size): Unit { - sortArrayWith(this, fromIndex, toIndex, comparator) -} - -/** - * Sorts the array in-place. - */ -public fun IntArray.sort(): Unit { - if (size > 1) sortArray(this) -} - -/** - * Sorts the array in-place. - */ -public fun LongArray.sort(): Unit { - if (size > 1) sortArray(this) -} - -/** - * Sorts the array in-place. - */ -public fun ByteArray.sort(): Unit { - if (size > 1) sortArray(this) -} - -/** - * Sorts the array in-place. - */ -public fun ShortArray.sort(): Unit { - if (size > 1) sortArray(this) -} - -/** - * Sorts the array in-place. - */ -public fun DoubleArray.sort(): Unit { - if (size > 1) sortArray(this) -} - -/** - * Sorts the array in-place. - */ -public fun FloatArray.sort(): Unit { - if (size > 1) sortArray(this) -} - -/** - * Sorts the array in-place. - */ -public fun CharArray.sort(): Unit { - if (size > 1) sortArray(this) -} - -/** - * Returns a *typed* object array containing all of the elements of this primitive array. - */ -public fun ByteArray.toTypedArray(): Array { - val result = arrayOfNulls(size) - for (index in indices) - result[index] = this[index] - @Suppress("UNCHECKED_CAST") - return result as Array -} - -/** - * Returns a *typed* object array containing all of the elements of this primitive array. - */ -public fun ShortArray.toTypedArray(): Array { - val result = arrayOfNulls(size) - for (index in indices) - result[index] = this[index] - @Suppress("UNCHECKED_CAST") - return result as Array -} - -/** - * Returns a *typed* object array containing all of the elements of this primitive array. - */ -public fun IntArray.toTypedArray(): Array { - val result = arrayOfNulls(size) - for (index in indices) - result[index] = this[index] - @Suppress("UNCHECKED_CAST") - return result as Array -} - -/** - * Returns a *typed* object array containing all of the elements of this primitive array. - */ -public fun LongArray.toTypedArray(): Array { - val result = arrayOfNulls(size) - for (index in indices) - result[index] = this[index] - @Suppress("UNCHECKED_CAST") - return result as Array -} - -/** - * Returns a *typed* object array containing all of the elements of this primitive array. - */ -public fun FloatArray.toTypedArray(): Array { - val result = arrayOfNulls(size) - for (index in indices) - result[index] = this[index] - @Suppress("UNCHECKED_CAST") - return result as Array -} - -/** - * Returns a *typed* object array containing all of the elements of this primitive array. - */ -public fun DoubleArray.toTypedArray(): Array { - val result = arrayOfNulls(size) - for (index in indices) - result[index] = this[index] - @Suppress("UNCHECKED_CAST") - return result as Array -} - -/** - * Returns a *typed* object array containing all of the elements of this primitive array. - */ -public fun BooleanArray.toTypedArray(): Array { - val result = arrayOfNulls(size) - for (index in indices) - result[index] = this[index] - @Suppress("UNCHECKED_CAST") - return result as Array -} - -/** - * Returns a *typed* object array containing all of the elements of this primitive array. - */ -public fun CharArray.toTypedArray(): Array { - val result = arrayOfNulls(size) - for (index in indices) - result[index] = this[index] - @Suppress("UNCHECKED_CAST") - return result as Array -} - -/** - * Returns a list of all elements sorted according to the specified [comparator]. - */ -public fun Array.sortedWith(comparator: Comparator): List { - return sortedArrayWith(comparator).asList() -} - -/** - * Returns a list of all elements sorted according to the specified [comparator]. - */ -public fun ByteArray.sortedWith(comparator: Comparator): List { - return toTypedArray().apply { sortWith(comparator) }.asList() -} - -/** - * Returns a list of all elements sorted according to the specified [comparator]. - */ -public fun ShortArray.sortedWith(comparator: Comparator): List { - return toTypedArray().apply { sortWith(comparator) }.asList() -} - -/** - * Returns a list of all elements sorted according to the specified [comparator]. - */ -public fun IntArray.sortedWith(comparator: Comparator): List { - return toTypedArray().apply { sortWith(comparator) }.asList() -} - -/** - * Returns a list of all elements sorted according to the specified [comparator]. - */ -public fun LongArray.sortedWith(comparator: Comparator): List { - return toTypedArray().apply { sortWith(comparator) }.asList() -} - -/** - * Returns a list of all elements sorted according to the specified [comparator]. - */ -public fun FloatArray.sortedWith(comparator: Comparator): List { - return toTypedArray().apply { sortWith(comparator) }.asList() -} - -/** - * Returns a list of all elements sorted according to the specified [comparator]. - */ -public fun DoubleArray.sortedWith(comparator: Comparator): List { - return toTypedArray().apply { sortWith(comparator) }.asList() -} - -/** - * Returns a list of all elements sorted according to the specified [comparator]. - */ -public fun BooleanArray.sortedWith(comparator: Comparator): List { - return toTypedArray().apply { sortWith(comparator) }.asList() -} - -/** - * Returns a list of all elements sorted according to the specified [comparator]. - */ -public fun CharArray.sortedWith(comparator: Comparator): List { - return toTypedArray().apply { sortWith(comparator) }.asList() -} - -/** - * Returns an array with all elements of this array sorted according the specified [comparator]. - */ -public fun Array.sortedArrayWith(comparator: Comparator): Array { - if (isEmpty()) return this - return this.copyOf().apply { sortWith(comparator) } -} - -/** - * Returns a string representation of the contents of the specified array as if it is [List]. - */ -@SinceKotlin("1.1") -@kotlin.internal.InlineOnly -public inline fun Array.contentToString(): String { - return this.subarrayContentToString(offset = 0, length = this.size) -} - -/** - * Returns a string representation of the contents of the specified array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun ByteArray.contentToString(): String { - if (size == 0) - return "[]" - val iMax = size - 1 - - val b = StringBuilder() - b.append('[') - var i = 0 - while (true) { - b.append(this[i]) - if (i == iMax) - return b.append(']').toString() - b.append(", ") - i++ - } -} - -/** - * Returns a string representation of the contents of the specified array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun ShortArray.contentToString(): String { - if (size == 0) - return "[]" - val iMax = size - 1 - - val b = StringBuilder() - b.append('[') - var i = 0 - while (true) { - b.append(this[i]) - if (i == iMax) - return b.append(']').toString() - b.append(", ") - i++ - } -} - -/** - * Returns a string representation of the contents of the specified array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun IntArray.contentToString(): String { - if (size == 0) - return "[]" - val iMax = size - 1 - - val b = StringBuilder() - b.append('[') - var i = 0 - while (true) { - b.append(this[i]) - if (i == iMax) - return b.append(']').toString() - b.append(", ") - i++ - } -} - -/** - * Returns a string representation of the contents of the specified array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun LongArray.contentToString(): String { - if (size == 0) - return "[]" - val iMax = size - 1 - - val b = StringBuilder() - b.append('[') - var i = 0 - while (true) { - b.append(this[i]) - if (i == iMax) - return b.append(']').toString() - b.append(", ") - i++ - } -} - -/** - * Returns a string representation of the contents of the specified array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun FloatArray.contentToString(): String { - if (size == 0) - return "[]" - val iMax = size - 1 - - val b = StringBuilder() - b.append('[') - var i = 0 - while (true) { - b.append(this[i]) - if (i == iMax) - return b.append(']').toString() - b.append(", ") - i++ - } -} - -/** - * Returns a string representation of the contents of the specified array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun DoubleArray.contentToString(): String { - if (size == 0) - return "[]" - val iMax = size - 1 - - val b = StringBuilder() - b.append('[') - var i = 0 - while (true) { - b.append(this[i]) - if (i == iMax) - return b.append(']').toString() - b.append(", ") - i++ - } -} - -/** - * Returns a string representation of the contents of the specified array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun BooleanArray.contentToString(): String { - if (size == 0) - return "[]" - val iMax = size - 1 - - val b = StringBuilder() - b.append('[') - var i = 0 - while (true) { - b.append(this[i]) - if (i == iMax) - return b.append(']').toString() - b.append(", ") - i++ - } -} - -/** - * Returns a string representation of the contents of the specified array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun CharArray.contentToString(): String { - if (size == 0) - return "[]" - val iMax = size - 1 - - val b = StringBuilder() - b.append('[') - var i = 0 - while (true) { - b.append(this[i]) - if (i == iMax) - return b.append(']').toString() - b.append(", ") - i++ - } -} - - -/** - * Returns a string representation of the contents of the subarray of the specified array as if it is [List]. - */ -@SinceKotlin("1.1") -@kotlin.internal.InlineOnly -public inline fun Array.subarrayContentToString(offset: Int, length: Int): String { - val sb = StringBuilder(2 + length * 3) - sb.append("[") - var i = 0 - while (i < length) { - if (i > 0) sb.append(", ") - sb.append(this[offset + i]) - i++ - } - sb.append("]") - return sb.toString() -} - -/** - * Returns `true` if the two specified arrays are *deeply* equal to one another, - * i.e. contain the same number of the same elements in the same order. - * - * If two corresponding elements are nested arrays, they are also compared deeply. - * If any of arrays contains itself on any nesting level the behavior is undefined. - */ -@SinceKotlin("1.1") -public infix fun Array.contentDeepEquals(other: Array): Boolean { - if (this === other) { - return true - } - - if (this.size != other.size) { - return false - } - - for (i in indices) { - val v1 = this[i] - val v2 = other[i] - - if (v1 == null || v2 == null) { - if (v1 == v2) { - continue - } else { - return false - } - } - - // TODO: Do a typecheck like if(v1.class == v2.class) return false - // Cases: - // Array - // Primitive array - // Some value (not an array) - - when { - v1 is Array<*> && v2 is Array<*> -> if (!v1.contentDeepEquals(v2)) return false - v1 is ByteArray && v2 is ByteArray -> if (!v1.contentEquals(v2)) return false - v1 is ShortArray && v2 is ShortArray -> if (!v1.contentEquals(v2)) return false - v1 is IntArray && v2 is IntArray -> if (!v1.contentEquals(v2)) return false - v1 is LongArray && v2 is LongArray -> if (!v1.contentEquals(v2)) return false - v1 is FloatArray && v2 is FloatArray -> if (!v1.contentEquals(v2)) return false - v1 is DoubleArray && v2 is DoubleArray -> if (!v1.contentEquals(v2)) return false - v1 is CharArray && v2 is CharArray -> if (!v1.contentEquals(v2)) return false - v1 is BooleanArray && v2 is BooleanArray -> if (!v1.contentEquals(v2)) return false - else -> if (v1 != v2) return false - } - - } - return true -} - -/** - * Returns a hash code based on the contents of this array as if it is [List]. - * Nested arrays are treated as lists too. - * - * If any of arrays contains itself on any nesting level the behavior is undefined. - */ -@SinceKotlin("1.1") -public fun Array.contentDeepHashCode(): Int { - var result = 1 - for (element in this) { - var elementHash = 0 - if (element is Array<*>) - elementHash = element.contentDeepHashCode() - else - element?.let { elementHash = element.hashCode() } - - result = 31 * result + elementHash - } - return result -} - -/** - * Returns a string representation of the contents of this array as if it is a [List]. - * Nested arrays are treated as lists too. - * - * If any of arrays contains itself on any nesting level that reference - * is rendered as `"[...]"` to prevent recursion. - */ -@SinceKotlin("1.1") -public fun Array.contentDeepToString(): String { - val length = if (size * 5 + 2 > 0) size * 5 + 2 else Int.MAX_VALUE - val result = StringBuilder(length) - contentDeepToStringInternal(result, mutableSetOf()) - return result.toString() -} - -private fun Array.contentDeepToStringInternal(result: StringBuilder, processed: MutableSet>) { - if (this in processed) { - result.append("[...]") - return - } - processed.add(this) - result.append('[') - - for (i in indices) { - if (i != 0) { - result.append(", ") - } - val element = this[i] - when (element) { - null -> result.append("null") - is Array<*> -> element.contentDeepToStringInternal(result, processed) - is ByteArray -> result.append(element.contentToString()) - is ShortArray -> result.append(element.contentToString()) - is IntArray -> result.append(element.contentToString()) - is LongArray -> result.append(element.contentToString()) - is FloatArray -> result.append(element.contentToString()) - is DoubleArray -> result.append(element.contentToString()) - is CharArray -> result.append(element.contentToString()) - is BooleanArray -> result.append(element.contentToString()) - else -> result.append(element.toString()) - } - } - - result.append(']') - processed.remove(this) -} - -/** - * Returns `true` if the two specified arrays are *structurally* equal to one another, - * i.e. contain the same number of the same elements in the same order. - */ -@SinceKotlin("1.1") -public infix fun Array.contentEquals(other: Array): Boolean { - if (this === other) { - return true - } - if (size != other.size) { - return false - } - for (i in indices) { - if (this[i] != other[i]) { - return false - } - } - return true; -} - -/** - * Returns `true` if the two specified arrays are *structurally* equal to one another, - * i.e. contain the same number of the same elements in the same order. - */ -@SinceKotlin("1.1") -public infix fun ByteArray.contentEquals(other: ByteArray): Boolean { - if (this === other) { - return true - } - if (size != other.size) { - return false - } - for (i in indices) { - if (this[i] != other[i]) { - return false - } - } - return true; -} - -/** - * Returns `true` if the two specified arrays are *structurally* equal to one another, - * i.e. contain the same number of the same elements in the same order. - */ -@SinceKotlin("1.1") -public infix fun ShortArray.contentEquals(other: ShortArray): Boolean { - if (this === other) { - return true - } - if (size != other.size) { - return false - } - for (i in indices) { - if (this[i] != other[i]) { - return false - } - } - return true; -} - -/** - * Returns `true` if the two specified arrays are *structurally* equal to one another, - * i.e. contain the same number of the same elements in the same order. - */ -@SinceKotlin("1.1") -public infix fun IntArray.contentEquals(other: IntArray): Boolean { - if (this === other) { - return true - } - if (size != other.size) { - return false - } - for (i in indices) { - if (this[i] != other[i]) { - return false - } - } - return true; -} - -/** - * Returns `true` if the two specified arrays are *structurally* equal to one another, - * i.e. contain the same number of the same elements in the same order. - */ -@SinceKotlin("1.1") -public infix fun LongArray.contentEquals(other: LongArray): Boolean { - if (this === other) { - return true - } - if (size != other.size) { - return false - } - for (i in indices) { - if (this[i] != other[i]) { - return false - } - } - return true; -} - -/** - * Returns `true` if the two specified arrays are *structurally* equal to one another, - * i.e. contain the same number of the same elements in the same order. - */ -@SinceKotlin("1.1") -public infix fun FloatArray.contentEquals(other: FloatArray): Boolean { - if (this === other) { - return true - } - if (size != other.size) { - return false - } - for (i in indices) { - if (this[i] != other[i]) { - return false - } - } - return true; -} - -/** - * Returns `true` if the two specified arrays are *structurally* equal to one another, - * i.e. contain the same number of the same elements in the same order. - */ -@SinceKotlin("1.1") -public infix fun DoubleArray.contentEquals(other: DoubleArray): Boolean { - if (this === other) { - return true - } - if (size != other.size) { - return false - } - for (i in indices) { - if (this[i] != other[i]) { - return false - } - } - return true; -} - -/** - * Returns `true` if the two specified arrays are *structurally* equal to one another, - * i.e. contain the same number of the same elements in the same order. - */ -@SinceKotlin("1.1") -public infix fun BooleanArray.contentEquals(other: BooleanArray): Boolean { - if (this === other) { - return true - } - if (size != other.size) { - return false - } - for (i in indices) { - if (this[i] != other[i]) { - return false - } - } - return true; -} - -/** - * Returns `true` if the two specified arrays are *structurally* equal to one another, - * i.e. contain the same number of the same elements in the same order. - */ -@SinceKotlin("1.1") -public infix fun CharArray.contentEquals(other: CharArray): Boolean { - if (this === other) { - return true - } - if (size != other.size) { - return false - } - for (i in indices) { - if (this[i] != other[i]) { - return false - } - } - return true; -} - -/** - * Returns a hash code based on the contents of this array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun Array.contentHashCode(): Int { - var result = 1 - for (element in this) - result = 31 * result + (element?.hashCode() ?: 0) - return result -} - -/** - * Returns a hash code based on the contents of this array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun ByteArray.contentHashCode(): Int { - var result = 1 - for (element in this) - result = 31 * result + element.hashCode() - return result -} - -/** - * Returns a hash code based on the contents of this array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun ShortArray.contentHashCode(): Int { - var result = 1 - for (element in this) - result = 31 * result + element.hashCode() - return result -} - -/** - * Returns a hash code based on the contents of this array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun IntArray.contentHashCode(): Int { - var result = 1 - for (element in this) - result = 31 * result + element.hashCode() - return result -} - -/** - * Returns a hash code based on the contents of this array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun LongArray.contentHashCode(): Int { - var result = 1 - for (element in this) - result = 31 * result + element.hashCode() - return result -} - -/** - * Returns a hash code based on the contents of this array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun FloatArray.contentHashCode(): Int { - var result = 1 - for (element in this) - result = 31 * result + element.hashCode() - return result -} - -/** - * Returns a hash code based on the contents of this array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun DoubleArray.contentHashCode(): Int { - var result = 1 - for (element in this) - result = 31 * result + element.hashCode() - return result -} - -/** - * Returns a hash code based on the contents of this array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun BooleanArray.contentHashCode(): Int { - var result = 1 - for (element in this) - result = 31 * result + element.hashCode() - return result -} - -/** - * Returns a hash code based on the contents of this array as if it is [List]. - */ -@SinceKotlin("1.1") -public fun CharArray.contentHashCode(): Int { - var result = 1 - for (element in this) - result = 31 * result + element.hashCode() - return result -} - -/** - * Returns an array of Boolean containing all of the elements of this generic array. - */ -public fun Array.toBooleanArray(): BooleanArray { - val result = BooleanArray(size) - for (index in indices) - result[index] = this[index] - return result -} - -/** - * Returns an array of Byte containing all of the elements of this generic array. - */ -public fun Array.toByteArray(): ByteArray { - val result = ByteArray(size) - for (index in indices) - result[index] = this[index] - return result -} - -/** - * Returns an array of Char containing all of the elements of this generic array. - */ -public fun Array.toCharArray(): CharArray { - val result = CharArray(size) - for (index in indices) - result[index] = this[index] - return result -} - -/** - * Returns an array of Double containing all of the elements of this generic array. - */ -public fun Array.toDoubleArray(): DoubleArray { - val result = DoubleArray(size) - for (index in indices) - result[index] = this[index] - return result -} - -/** - * Returns an array of Float containing all of the elements of this generic array. - */ -public fun Array.toFloatArray(): FloatArray { - val result = FloatArray(size) - for (index in indices) - result[index] = this[index] - return result -} - -/** - * Returns an array of Int containing all of the elements of this generic array. - */ -public fun Array.toIntArray(): IntArray { - val result = IntArray(size) - for (index in indices) - result[index] = this[index] - return result -} - -/** - * Returns an array of Long containing all of the elements of this generic array. - */ -public fun Array.toLongArray(): LongArray { - val result = LongArray(size) - for (index in indices) - result[index] = this[index] - return result -} - -/** - * Returns an array of Short containing all of the elements of this generic array. - */ -public fun Array.toShortArray(): ShortArray { - val result = ShortArray(size) - for (index in indices) - result[index] = this[index] - return result -} - -/** - * Returns a [Map] containing key-value pairs provided by [transform] function - * applied to elements of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun Array.associate(transform: (T) -> Pair): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateTo(LinkedHashMap(capacity), transform) -} - -/** - * Returns a [Map] containing key-value pairs provided by [transform] function - * applied to elements of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun ByteArray.associate(transform: (Byte) -> Pair): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateTo(LinkedHashMap(capacity), transform) -} - -/** - * Returns a [Map] containing key-value pairs provided by [transform] function - * applied to elements of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun ShortArray.associate(transform: (Short) -> Pair): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateTo(LinkedHashMap(capacity), transform) -} - -/** - * Returns a [Map] containing key-value pairs provided by [transform] function - * applied to elements of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun IntArray.associate(transform: (Int) -> Pair): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateTo(LinkedHashMap(capacity), transform) -} - -/** - * Returns a [Map] containing key-value pairs provided by [transform] function - * applied to elements of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun LongArray.associate(transform: (Long) -> Pair): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateTo(LinkedHashMap(capacity), transform) -} - -/** - * Returns a [Map] containing key-value pairs provided by [transform] function - * applied to elements of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun FloatArray.associate(transform: (Float) -> Pair): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateTo(LinkedHashMap(capacity), transform) -} - -/** - * Returns a [Map] containing key-value pairs provided by [transform] function - * applied to elements of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun DoubleArray.associate(transform: (Double) -> Pair): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateTo(LinkedHashMap(capacity), transform) -} - -/** - * Returns a [Map] containing key-value pairs provided by [transform] function - * applied to elements of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun BooleanArray.associate(transform: (Boolean) -> Pair): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateTo(LinkedHashMap(capacity), transform) -} - -/** - * Returns a [Map] containing key-value pairs provided by [transform] function - * applied to elements of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun CharArray.associate(transform: (Char) -> Pair): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateTo(LinkedHashMap(capacity), transform) -} - -/** - * Returns a [Map] containing the elements from the given array indexed by the key - * returned from [keySelector] function applied to each element. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun Array.associateBy(keySelector: (T) -> K): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector) -} - -/** - * Returns a [Map] containing the elements from the given array indexed by the key - * returned from [keySelector] function applied to each element. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun ByteArray.associateBy(keySelector: (Byte) -> K): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector) -} - -/** - * Returns a [Map] containing the elements from the given array indexed by the key - * returned from [keySelector] function applied to each element. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun ShortArray.associateBy(keySelector: (Short) -> K): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector) -} - -/** - * Returns a [Map] containing the elements from the given array indexed by the key - * returned from [keySelector] function applied to each element. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun IntArray.associateBy(keySelector: (Int) -> K): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector) -} - -/** - * Returns a [Map] containing the elements from the given array indexed by the key - * returned from [keySelector] function applied to each element. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun LongArray.associateBy(keySelector: (Long) -> K): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector) -} - -/** - * Returns a [Map] containing the elements from the given array indexed by the key - * returned from [keySelector] function applied to each element. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun FloatArray.associateBy(keySelector: (Float) -> K): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector) -} - -/** - * Returns a [Map] containing the elements from the given array indexed by the key - * returned from [keySelector] function applied to each element. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun DoubleArray.associateBy(keySelector: (Double) -> K): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector) -} - -/** - * Returns a [Map] containing the elements from the given array indexed by the key - * returned from [keySelector] function applied to each element. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun BooleanArray.associateBy(keySelector: (Boolean) -> K): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector) -} - -/** - * Returns a [Map] containing the elements from the given array indexed by the key - * returned from [keySelector] function applied to each element. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun CharArray.associateBy(keySelector: (Char) -> K): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector) -} - -/** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun Array.associateBy(keySelector: (T) -> K, valueTransform: (T) -> V): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) -} - -/** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun ByteArray.associateBy(keySelector: (Byte) -> K, valueTransform: (Byte) -> V): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) -} - -/** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun ShortArray.associateBy(keySelector: (Short) -> K, valueTransform: (Short) -> V): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) -} - -/** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun IntArray.associateBy(keySelector: (Int) -> K, valueTransform: (Int) -> V): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) -} - -/** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun LongArray.associateBy(keySelector: (Long) -> K, valueTransform: (Long) -> V): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) -} - -/** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun FloatArray.associateBy(keySelector: (Float) -> K, valueTransform: (Float) -> V): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) -} - -/** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun DoubleArray.associateBy(keySelector: (Double) -> K, valueTransform: (Double) -> V): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) -} - -/** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun BooleanArray.associateBy(keySelector: (Boolean) -> K, valueTransform: (Boolean) -> V): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) -} - -/** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original array. - */ -public inline fun CharArray.associateBy(keySelector: (Char) -> K, valueTransform: (Char) -> V): Map { - val capacity = mapCapacity(size).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function applied to each element of the given array - * and value is the element itself. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > Array.associateByTo(destination: M, keySelector: (T) -> K): M { - for (element in this) { - destination.put(keySelector(element), element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function applied to each element of the given array - * and value is the element itself. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > ByteArray.associateByTo(destination: M, keySelector: (Byte) -> K): M { - for (element in this) { - destination.put(keySelector(element), element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function applied to each element of the given array - * and value is the element itself. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > ShortArray.associateByTo(destination: M, keySelector: (Short) -> K): M { - for (element in this) { - destination.put(keySelector(element), element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function applied to each element of the given array - * and value is the element itself. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > IntArray.associateByTo(destination: M, keySelector: (Int) -> K): M { - for (element in this) { - destination.put(keySelector(element), element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function applied to each element of the given array - * and value is the element itself. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > LongArray.associateByTo(destination: M, keySelector: (Long) -> K): M { - for (element in this) { - destination.put(keySelector(element), element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function applied to each element of the given array - * and value is the element itself. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > FloatArray.associateByTo(destination: M, keySelector: (Float) -> K): M { - for (element in this) { - destination.put(keySelector(element), element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function applied to each element of the given array - * and value is the element itself. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > DoubleArray.associateByTo(destination: M, keySelector: (Double) -> K): M { - for (element in this) { - destination.put(keySelector(element), element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function applied to each element of the given array - * and value is the element itself. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > BooleanArray.associateByTo(destination: M, keySelector: (Boolean) -> K): M { - for (element in this) { - destination.put(keySelector(element), element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function applied to each element of the given array - * and value is the element itself. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > CharArray.associateByTo(destination: M, keySelector: (Char) -> K): M { - for (element in this) { - destination.put(keySelector(element), element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and - * and value is provided by the [valueTransform] function applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > Array.associateByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V): M { - for (element in this) { - destination.put(keySelector(element), valueTransform(element)) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and - * and value is provided by the [valueTransform] function applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > ByteArray.associateByTo(destination: M, keySelector: (Byte) -> K, valueTransform: (Byte) -> V): M { - for (element in this) { - destination.put(keySelector(element), valueTransform(element)) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and - * and value is provided by the [valueTransform] function applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > ShortArray.associateByTo(destination: M, keySelector: (Short) -> K, valueTransform: (Short) -> V): M { - for (element in this) { - destination.put(keySelector(element), valueTransform(element)) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and - * and value is provided by the [valueTransform] function applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > IntArray.associateByTo(destination: M, keySelector: (Int) -> K, valueTransform: (Int) -> V): M { - for (element in this) { - destination.put(keySelector(element), valueTransform(element)) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and - * and value is provided by the [valueTransform] function applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > LongArray.associateByTo(destination: M, keySelector: (Long) -> K, valueTransform: (Long) -> V): M { - for (element in this) { - destination.put(keySelector(element), valueTransform(element)) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and - * and value is provided by the [valueTransform] function applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > FloatArray.associateByTo(destination: M, keySelector: (Float) -> K, valueTransform: (Float) -> V): M { - for (element in this) { - destination.put(keySelector(element), valueTransform(element)) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and - * and value is provided by the [valueTransform] function applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > DoubleArray.associateByTo(destination: M, keySelector: (Double) -> K, valueTransform: (Double) -> V): M { - for (element in this) { - destination.put(keySelector(element), valueTransform(element)) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and - * and value is provided by the [valueTransform] function applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > BooleanArray.associateByTo(destination: M, keySelector: (Boolean) -> K, valueTransform: (Boolean) -> V): M { - for (element in this) { - destination.put(keySelector(element), valueTransform(element)) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and - * and value is provided by the [valueTransform] function applied to elements of the given array. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > CharArray.associateByTo(destination: M, keySelector: (Char) -> K, valueTransform: (Char) -> V): M { - for (element in this) { - destination.put(keySelector(element), valueTransform(element)) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs - * provided by [transform] function applied to each element of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - */ -public inline fun > Array.associateTo(destination: M, transform: (T) -> Pair): M { - for (element in this) { - destination += transform(element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs - * provided by [transform] function applied to each element of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - */ -public inline fun > ByteArray.associateTo(destination: M, transform: (Byte) -> Pair): M { - for (element in this) { - destination += transform(element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs - * provided by [transform] function applied to each element of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - */ -public inline fun > ShortArray.associateTo(destination: M, transform: (Short) -> Pair): M { - for (element in this) { - destination += transform(element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs - * provided by [transform] function applied to each element of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - */ -public inline fun > IntArray.associateTo(destination: M, transform: (Int) -> Pair): M { - for (element in this) { - destination += transform(element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs - * provided by [transform] function applied to each element of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - */ -public inline fun > LongArray.associateTo(destination: M, transform: (Long) -> Pair): M { - for (element in this) { - destination += transform(element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs - * provided by [transform] function applied to each element of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - */ -public inline fun > FloatArray.associateTo(destination: M, transform: (Float) -> Pair): M { - for (element in this) { - destination += transform(element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs - * provided by [transform] function applied to each element of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - */ -public inline fun > DoubleArray.associateTo(destination: M, transform: (Double) -> Pair): M { - for (element in this) { - destination += transform(element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs - * provided by [transform] function applied to each element of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - */ -public inline fun > BooleanArray.associateTo(destination: M, transform: (Boolean) -> Pair): M { - for (element in this) { - destination += transform(element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs - * provided by [transform] function applied to each element of the given array. - * - * If any of two pairs would have the same key the last one gets added to the map. - */ -public inline fun > CharArray.associateTo(destination: M, transform: (Char) -> Pair): M { - for (element in this) { - destination += transform(element) - } - return destination -} - -// From Library.kt. -/** - * Returns an array of objects of the given type with the given [size], initialized with null values. - */ -public inline fun arrayOfNulls(size: Int): Array = - @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") - arrayOfUninitializedElements(size) - -/** - * Returns a *typed* array containing all of the elements of this collection. - * - * Allocates an array of runtime type `T` having its size equal to the size of this collection - * and populates the array with the elements of this collection. - */ -public inline fun Collection.toTypedArray(): Array { - val result = arrayOfNulls(size) - var index = 0 - for (element in this) result[index++] = element - @Suppress("UNCHECKED_CAST") - return result as Array -} - /** * Returns an array containing the specified elements. */ @@ -12717,1637 +485,3 @@ public inline fun byteArrayOf(vararg elements: Byte) = elements */ @Suppress("NOTHING_TO_INLINE") public inline fun booleanArrayOf(vararg elements: Boolean) = elements - -/** - * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun Array.joinTo( - buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", - limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): A { - buffer.append(prefix) - var count = 0 - for (element in this) { - if (++count > 1) buffer.append(separator) - if (limit < 0 || count <= limit) { - buffer.appendElement(element, transform) - } else break - } - if (limit >= 0 && count > limit) buffer.append(truncated) - buffer.append(postfix) - return buffer -} - -/** - * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun ByteArray.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Byte) -> CharSequence)? = null): A { - buffer.append(prefix) - var count = 0 - for (element in this) { - if (++count > 1) buffer.append(separator) - if (limit < 0 || count <= limit) { - if (transform != null) - buffer.append(transform(element)) - else - buffer.append(element.toString()) - } else break - } - if (limit >= 0 && count > limit) buffer.append(truncated) - buffer.append(postfix) - return buffer -} - -/** - * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun ShortArray.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Short) -> CharSequence)? = null): A { - buffer.append(prefix) - var count = 0 - for (element in this) { - if (++count > 1) buffer.append(separator) - if (limit < 0 || count <= limit) { - if (transform != null) - buffer.append(transform(element)) - else - buffer.append(element.toString()) - } else break - } - if (limit >= 0 && count > limit) buffer.append(truncated) - buffer.append(postfix) - return buffer -} - -/** - * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun IntArray.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Int) -> CharSequence)? = null): A { - buffer.append(prefix) - var count = 0 - for (element in this) { - if (++count > 1) buffer.append(separator) - if (limit < 0 || count <= limit) { - if (transform != null) - buffer.append(transform(element)) - else - buffer.append(element.toString()) - } else break - } - if (limit >= 0 && count > limit) buffer.append(truncated) - buffer.append(postfix) - return buffer -} - -/** - * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun LongArray.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Long) -> CharSequence)? = null): A { - buffer.append(prefix) - var count = 0 - for (element in this) { - if (++count > 1) buffer.append(separator) - if (limit < 0 || count <= limit) { - if (transform != null) - buffer.append(transform(element)) - else - buffer.append(element.toString()) - } else break - } - if (limit >= 0 && count > limit) buffer.append(truncated) - buffer.append(postfix) - return buffer -} - -/** - * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun FloatArray.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Float) -> CharSequence)? = null): A { - buffer.append(prefix) - var count = 0 - for (element in this) { - if (++count > 1) buffer.append(separator) - if (limit < 0 || count <= limit) { - if (transform != null) - buffer.append(transform(element)) - else - buffer.append(element.toString()) - } else break - } - if (limit >= 0 && count > limit) buffer.append(truncated) - buffer.append(postfix) - return buffer -} - -/** - * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun DoubleArray.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Double) -> CharSequence)? = null): A { - buffer.append(prefix) - var count = 0 - for (element in this) { - if (++count > 1) buffer.append(separator) - if (limit < 0 || count <= limit) { - if (transform != null) - buffer.append(transform(element)) - else - buffer.append(element.toString()) - } else break - } - if (limit >= 0 && count > limit) buffer.append(truncated) - buffer.append(postfix) - return buffer -} - -/** - * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun BooleanArray.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", - postfix: CharSequence = "", limit: Int = -1, - truncated: CharSequence = "...", - transform: ((Boolean) -> CharSequence)? = null): A { - buffer.append(prefix) - var count = 0 - for (element in this) { - if (++count > 1) buffer.append(separator) - if (limit < 0 || count <= limit) { - if (transform != null) - buffer.append(transform(element)) - else - buffer.append(element.toString()) - } else break - } - if (limit >= 0 && count > limit) buffer.append(truncated) - buffer.append(postfix) - return buffer -} - -/** - * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun CharArray.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", - limit: Int = -1, truncated: CharSequence = "...", transform: ((Char) -> CharSequence)? = null): A { - buffer.append(prefix) - var count = 0 - for (element in this) { - if (++count > 1) buffer.append(separator) - if (limit < 0 || count <= limit) { - if (transform != null) - buffer.append(transform(element)) - else - buffer.append(element) - } else break - } - if (limit >= 0 && count > limit) buffer.append(truncated) - buffer.append(postfix) - return buffer -} - -/** - * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun Array.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String { - return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() -} - -/** - * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun ByteArray.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Byte) -> CharSequence)? = null): String { - return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() -} - -/** - * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun ShortArray.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Short) -> CharSequence)? = null): String { - return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() -} - -/** - * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun IntArray.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Int) -> CharSequence)? = null): String { - return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() -} - -/** - * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun LongArray.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Long) -> CharSequence)? = null): String { - return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() -} - -/** - * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun FloatArray.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Float) -> CharSequence)? = null): String { - return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() -} - -/** - * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun DoubleArray.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Double) -> CharSequence)? = null): String { - return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() -} - -/** - * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun BooleanArray.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Boolean) -> CharSequence)? = null): String { - return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() -} - -/** - * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun CharArray.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((Char) -> CharSequence)? = null): String { - return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() -} - -/** - * Creates an [Iterable] instance that wraps the original array returning its elements when being iterated. - */ -public fun Array.asIterable(): Iterable { - if (isEmpty()) return emptyList() - return Iterable { this.iterator() } -} - -/** - * Creates an [Iterable] instance that wraps the original array returning its elements when being iterated. - */ -public fun ByteArray.asIterable(): Iterable { - if (isEmpty()) return emptyList() - return Iterable { this.iterator() } -} - -/** - * Creates an [Iterable] instance that wraps the original array returning its elements when being iterated. - */ -public fun ShortArray.asIterable(): Iterable { - if (isEmpty()) return emptyList() - return Iterable { this.iterator() } -} - -/** - * Creates an [Iterable] instance that wraps the original array returning its elements when being iterated. - */ -public fun IntArray.asIterable(): Iterable { - if (isEmpty()) return emptyList() - return Iterable { this.iterator() } -} - -/** - * Creates an [Iterable] instance that wraps the original array returning its elements when being iterated. - */ -public fun LongArray.asIterable(): Iterable { - if (isEmpty()) return emptyList() - return Iterable { this.iterator() } -} - -/** - * Creates an [Iterable] instance that wraps the original array returning its elements when being iterated. - */ -public fun FloatArray.asIterable(): Iterable { - if (isEmpty()) return emptyList() - return Iterable { this.iterator() } -} - -/** - * Creates an [Iterable] instance that wraps the original array returning its elements when being iterated. - */ -public fun DoubleArray.asIterable(): Iterable { - if (isEmpty()) return emptyList() - return Iterable { this.iterator() } -} - -/** - * Creates an [Iterable] instance that wraps the original array returning its elements when being iterated. - */ -public fun BooleanArray.asIterable(): Iterable { - if (isEmpty()) return emptyList() - return Iterable { this.iterator() } -} - -/** - * Creates an [Iterable] instance that wraps the original array returning its elements when being iterated. - */ -public fun CharArray.asIterable(): Iterable { - if (isEmpty()) return emptyList() - return Iterable { this.iterator() } -} - -/** - * Creates a [Sequence] instance that wraps the original array returning its elements when being iterated. - * - * @sample samples.collections.Sequences.Building.sequenceFromArray - */ -public fun Array.asSequence(): Sequence { - if (isEmpty()) return emptySequence() - return Sequence { this.iterator() } -} - -/** - * Creates a [Sequence] instance that wraps the original array returning its elements when being iterated. - * - * @sample samples.collections.Sequences.Building.sequenceFromArray - */ -public fun ByteArray.asSequence(): Sequence { - if (isEmpty()) return emptySequence() - return Sequence { this.iterator() } -} - -/** - * Creates a [Sequence] instance that wraps the original array returning its elements when being iterated. - * - * @sample samples.collections.Sequences.Building.sequenceFromArray - */ -public fun ShortArray.asSequence(): Sequence { - if (isEmpty()) return emptySequence() - return Sequence { this.iterator() } -} - -/** - * Creates a [Sequence] instance that wraps the original array returning its elements when being iterated. - * - * @sample samples.collections.Sequences.Building.sequenceFromArray - */ -public fun IntArray.asSequence(): Sequence { - if (isEmpty()) return emptySequence() - return Sequence { this.iterator() } -} - -/** - * Creates a [Sequence] instance that wraps the original array returning its elements when being iterated. - * - * @sample samples.collections.Sequences.Building.sequenceFromArray - */ -public fun LongArray.asSequence(): Sequence { - if (isEmpty()) return emptySequence() - return Sequence { this.iterator() } -} - -/** - * Creates a [Sequence] instance that wraps the original array returning its elements when being iterated. - * - * @sample samples.collections.Sequences.Building.sequenceFromArray - */ -public fun FloatArray.asSequence(): Sequence { - if (isEmpty()) return emptySequence() - return Sequence { this.iterator() } -} - -/** - * Creates a [Sequence] instance that wraps the original array returning its elements when being iterated. - * - * @sample samples.collections.Sequences.Building.sequenceFromArray - */ -public fun DoubleArray.asSequence(): Sequence { - if (isEmpty()) return emptySequence() - return Sequence { this.iterator() } -} - -/** - * Creates a [Sequence] instance that wraps the original array returning its elements when being iterated. - * - * @sample samples.collections.Sequences.Building.sequenceFromArray - */ -public fun BooleanArray.asSequence(): Sequence { - if (isEmpty()) return emptySequence() - return Sequence { this.iterator() } -} - -/** - * Creates a [Sequence] instance that wraps the original array returning its elements when being iterated. - * - * @sample samples.collections.Sequences.Building.sequenceFromArray - */ -public fun CharArray.asSequence(): Sequence { - if (isEmpty()) return emptySequence() - return Sequence { this.iterator() } -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun Array.sumBy(selector: (T) -> Int): Int { - var sum: Int = 0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun ByteArray.sumBy(selector: (Byte) -> Int): Int { - var sum: Int = 0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun ShortArray.sumBy(selector: (Short) -> Int): Int { - var sum: Int = 0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun IntArray.sumBy(selector: (Int) -> Int): Int { - var sum: Int = 0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun LongArray.sumBy(selector: (Long) -> Int): Int { - var sum: Int = 0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun FloatArray.sumBy(selector: (Float) -> Int): Int { - var sum: Int = 0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun DoubleArray.sumBy(selector: (Double) -> Int): Int { - var sum: Int = 0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun BooleanArray.sumBy(selector: (Boolean) -> Int): Int { - var sum: Int = 0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun CharArray.sumBy(selector: (Char) -> Int): Int { - var sum: Int = 0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun Array.sumByDouble(selector: (T) -> Double): Double { - var sum: Double = 0.0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun ByteArray.sumByDouble(selector: (Byte) -> Double): Double { - var sum: Double = 0.0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun ShortArray.sumByDouble(selector: (Short) -> Double): Double { - var sum: Double = 0.0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun IntArray.sumByDouble(selector: (Int) -> Double): Double { - var sum: Double = 0.0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun LongArray.sumByDouble(selector: (Long) -> Double): Double { - var sum: Double = 0.0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun FloatArray.sumByDouble(selector: (Float) -> Double): Double { - var sum: Double = 0.0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun DoubleArray.sumByDouble(selector: (Double) -> Double): Double { - var sum: Double = 0.0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun BooleanArray.sumByDouble(selector: (Boolean) -> Double): Double { - var sum: Double = 0.0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the array. - */ -public inline fun CharArray.sumByDouble(selector: (Char) -> Double): Double { - var sum: Double = 0.0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns an original collection containing all the non-`null` elements, throwing an [IllegalArgumentException] if there are any `null` elements. - */ -public fun Array.requireNoNulls(): Array { - for (element in this) { - if (element == null) { - throw IllegalArgumentException("null element found in $this.") - } - } - @Suppress("UNCHECKED_CAST") - return this as Array -} - -/** - * Splits the original array into pair of lists, - * where *first* list contains elements for which [predicate] yielded `true`, - * while *second* list contains elements for which [predicate] yielded `false`. - */ -public inline fun Array.partition(predicate: (T) -> Boolean): Pair, List> { - val first = ArrayList() - val second = ArrayList() - for (element in this) { - if (predicate(element)) { - first.add(element) - } else { - second.add(element) - } - } - return Pair(first, second) -} - -/** - * Splits the original array into pair of lists, - * where *first* list contains elements for which [predicate] yielded `true`, - * while *second* list contains elements for which [predicate] yielded `false`. - */ -public inline fun ByteArray.partition(predicate: (Byte) -> Boolean): Pair, List> { - val first = ArrayList() - val second = ArrayList() - for (element in this) { - if (predicate(element)) { - first.add(element) - } else { - second.add(element) - } - } - return Pair(first, second) -} - -/** - * Splits the original array into pair of lists, - * where *first* list contains elements for which [predicate] yielded `true`, - * while *second* list contains elements for which [predicate] yielded `false`. - */ -public inline fun ShortArray.partition(predicate: (Short) -> Boolean): Pair, List> { - val first = ArrayList() - val second = ArrayList() - for (element in this) { - if (predicate(element)) { - first.add(element) - } else { - second.add(element) - } - } - return Pair(first, second) -} - -/** - * Splits the original array into pair of lists, - * where *first* list contains elements for which [predicate] yielded `true`, - * while *second* list contains elements for which [predicate] yielded `false`. - */ -public inline fun IntArray.partition(predicate: (Int) -> Boolean): Pair, List> { - val first = ArrayList() - val second = ArrayList() - for (element in this) { - if (predicate(element)) { - first.add(element) - } else { - second.add(element) - } - } - return Pair(first, second) -} - -/** - * Splits the original array into pair of lists, - * where *first* list contains elements for which [predicate] yielded `true`, - * while *second* list contains elements for which [predicate] yielded `false`. - */ -public inline fun LongArray.partition(predicate: (Long) -> Boolean): Pair, List> { - val first = ArrayList() - val second = ArrayList() - for (element in this) { - if (predicate(element)) { - first.add(element) - } else { - second.add(element) - } - } - return Pair(first, second) -} - -/** - * Splits the original array into pair of lists, - * where *first* list contains elements for which [predicate] yielded `true`, - * while *second* list contains elements for which [predicate] yielded `false`. - */ -public inline fun FloatArray.partition(predicate: (Float) -> Boolean): Pair, List> { - val first = ArrayList() - val second = ArrayList() - for (element in this) { - if (predicate(element)) { - first.add(element) - } else { - second.add(element) - } - } - return Pair(first, second) -} - -/** - * Splits the original array into pair of lists, - * where *first* list contains elements for which [predicate] yielded `true`, - * while *second* list contains elements for which [predicate] yielded `false`. - */ -public inline fun DoubleArray.partition(predicate: (Double) -> Boolean): Pair, List> { - val first = ArrayList() - val second = ArrayList() - for (element in this) { - if (predicate(element)) { - first.add(element) - } else { - second.add(element) - } - } - return Pair(first, second) -} - -/** - * Splits the original array into pair of lists, - * where *first* list contains elements for which [predicate] yielded `true`, - * while *second* list contains elements for which [predicate] yielded `false`. - */ -public inline fun BooleanArray.partition(predicate: (Boolean) -> Boolean): Pair, List> { - val first = ArrayList() - val second = ArrayList() - for (element in this) { - if (predicate(element)) { - first.add(element) - } else { - second.add(element) - } - } - return Pair(first, second) -} - -/** - * Splits the original array into pair of lists, - * where *first* list contains elements for which [predicate] yielded `true`, - * while *second* list contains elements for which [predicate] yielded `false`. - */ -public inline fun CharArray.partition(predicate: (Char) -> Boolean): Pair, List> { - val first = ArrayList() - val second = ArrayList() - for (element in this) { - if (predicate(element)) { - first.add(element) - } else { - second.add(element) - } - } - return Pair(first, second) -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun Array.zip(other: Array): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun ByteArray.zip(other: Array): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun ShortArray.zip(other: Array): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun IntArray.zip(other: Array): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun LongArray.zip(other: Array): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun FloatArray.zip(other: Array): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun DoubleArray.zip(other: Array): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun BooleanArray.zip(other: Array): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun CharArray.zip(other: Array): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun Array.zip(other: Array, transform: (a: T, b: R) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun ByteArray.zip(other: Array, transform: (a: Byte, b: R) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun ShortArray.zip(other: Array, transform: (a: Short, b: R) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun IntArray.zip(other: Array, transform: (a: Int, b: R) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun LongArray.zip(other: Array, transform: (a: Long, b: R) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun FloatArray.zip(other: Array, transform: (a: Float, b: R) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun DoubleArray.zip(other: Array, transform: (a: Double, b: R) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun BooleanArray.zip(other: Array, transform: (a: Boolean, b: R) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun CharArray.zip(other: Array, transform: (a: Char, b: R) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun Array.zip(other: Iterable): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun ByteArray.zip(other: Iterable): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun ShortArray.zip(other: Iterable): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun IntArray.zip(other: Iterable): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun LongArray.zip(other: Iterable): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun FloatArray.zip(other: Iterable): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun DoubleArray.zip(other: Iterable): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun BooleanArray.zip(other: Iterable): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun CharArray.zip(other: Iterable): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun Array.zip(other: Iterable, transform: (a: T, b: R) -> V): List { - val arraySize = size - val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) - var i = 0 - for (element in other) { - if (i >= arraySize) break - list.add(transform(this[i++], element)) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun ByteArray.zip(other: Iterable, transform: (a: Byte, b: R) -> V): List { - val arraySize = size - val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) - var i = 0 - for (element in other) { - if (i >= arraySize) break - list.add(transform(this[i++], element)) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun ShortArray.zip(other: Iterable, transform: (a: Short, b: R) -> V): List { - val arraySize = size - val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) - var i = 0 - for (element in other) { - if (i >= arraySize) break - list.add(transform(this[i++], element)) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun IntArray.zip(other: Iterable, transform: (a: Int, b: R) -> V): List { - val arraySize = size - val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) - var i = 0 - for (element in other) { - if (i >= arraySize) break - list.add(transform(this[i++], element)) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun LongArray.zip(other: Iterable, transform: (a: Long, b: R) -> V): List { - val arraySize = size - val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) - var i = 0 - for (element in other) { - if (i >= arraySize) break - list.add(transform(this[i++], element)) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun FloatArray.zip(other: Iterable, transform: (a: Float, b: R) -> V): List { - val arraySize = size - val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) - var i = 0 - for (element in other) { - if (i >= arraySize) break - list.add(transform(this[i++], element)) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun DoubleArray.zip(other: Iterable, transform: (a: Double, b: R) -> V): List { - val arraySize = size - val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) - var i = 0 - for (element in other) { - if (i >= arraySize) break - list.add(transform(this[i++], element)) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun BooleanArray.zip(other: Iterable, transform: (a: Boolean, b: R) -> V): List { - val arraySize = size - val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) - var i = 0 - for (element in other) { - if (i >= arraySize) break - list.add(transform(this[i++], element)) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun CharArray.zip(other: Iterable, transform: (a: Char, b: R) -> V): List { - val arraySize = size - val list = ArrayList(minOf(other.collectionSizeOrDefault(10), arraySize)) - var i = 0 - for (element in other) { - if (i >= arraySize) break - list.add(transform(this[i++], element)) - } - return list -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun ByteArray.zip(other: ByteArray): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun ShortArray.zip(other: ShortArray): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun IntArray.zip(other: IntArray): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun LongArray.zip(other: LongArray): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun FloatArray.zip(other: FloatArray): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun DoubleArray.zip(other: DoubleArray): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun BooleanArray.zip(other: BooleanArray): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun CharArray.zip(other: CharArray): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun ByteArray.zip(other: ByteArray, transform: (a: Byte, b: Byte) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun ShortArray.zip(other: ShortArray, transform: (a: Short, b: Short) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun IntArray.zip(other: IntArray, transform: (a: Int, b: Int) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun LongArray.zip(other: LongArray, transform: (a: Long, b: Long) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun FloatArray.zip(other: FloatArray, transform: (a: Float, b: Float) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun DoubleArray.zip(other: DoubleArray, transform: (a: Double, b: Double) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun BooleanArray.zip(other: BooleanArray, transform: (a: Boolean, b: Boolean) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun CharArray.zip(other: CharArray, transform: (a: Char, b: Char) -> V): List { - val size = minOf(size, other.size) - val list = ArrayList(size) - for (i in 0..size-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns an array containing all elements of the original array and then the given [element]. - */ -public operator fun Array.plus(element: T): Array { - val index = size - val result = copyOfUninitializedElements(index + 1) - result[index] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then the given [element]. - */ -public operator fun ByteArray.plus(element: Byte): ByteArray { - val index = size - val result = copyOfUninitializedElements(index + 1) - result[index] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then the given [element]. - */ -public operator fun ShortArray.plus(element: Short): ShortArray { - val index = size - val result = copyOfUninitializedElements(index + 1) - result[index] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then the given [element]. - */ -public operator fun IntArray.plus(element: Int): IntArray { - val index = size - val result = copyOfUninitializedElements(index + 1) - result[index] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then the given [element]. - */ -public operator fun LongArray.plus(element: Long): LongArray { - val index = size - val result = copyOfUninitializedElements(index + 1) - result[index] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then the given [element]. - */ -public operator fun FloatArray.plus(element: Float): FloatArray { - val index = size - val result = copyOfUninitializedElements(index + 1) - result[index] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then the given [element]. - */ -public operator fun DoubleArray.plus(element: Double): DoubleArray { - val index = size - val result = copyOfUninitializedElements(index + 1) - result[index] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then the given [element]. - */ -public operator fun BooleanArray.plus(element: Boolean): BooleanArray { - val index = size - val result = copyOfUninitializedElements(index + 1) - result[index] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then the given [element]. - */ -public operator fun CharArray.plus(element: Char): CharArray { - val index = size - val result = copyOfUninitializedElements(index + 1) - result[index] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. - */ -public operator fun Array.plus(elements: Collection): Array { - var index = size - val result = copyOfUninitializedElements(index + elements.size) - for (element in elements) result[index++] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. - */ -public operator fun ByteArray.plus(elements: Collection): ByteArray { - var index = size - val result = copyOfUninitializedElements(index + elements.size) - for (element in elements) result[index++] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. - */ -public operator fun ShortArray.plus(elements: Collection): ShortArray { - var index = size - val result = copyOfUninitializedElements(index + elements.size) - for (element in elements) result[index++] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. - */ -public operator fun IntArray.plus(elements: Collection): IntArray { - var index = size - val result = copyOfUninitializedElements(index + elements.size) - for (element in elements) result[index++] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. - */ -public operator fun LongArray.plus(elements: Collection): LongArray { - var index = size - val result = copyOfUninitializedElements(index + elements.size) - for (element in elements) result[index++] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. - */ -public operator fun FloatArray.plus(elements: Collection): FloatArray { - var index = size - val result = copyOfUninitializedElements(index + elements.size) - for (element in elements) result[index++] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. - */ -public operator fun DoubleArray.plus(elements: Collection): DoubleArray { - var index = size - val result = copyOfUninitializedElements(index + elements.size) - for (element in elements) result[index++] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. - */ -public operator fun BooleanArray.plus(elements: Collection): BooleanArray { - var index = size - val result = copyOfUninitializedElements(index + elements.size) - for (element in elements) result[index++] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. - */ -public operator fun CharArray.plus(elements: Collection): CharArray { - var index = size - val result = copyOfUninitializedElements(index + elements.size) - for (element in elements) result[index++] = element - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] array. - */ -public operator fun Array.plus(elements: Array): Array { - val thisSize = size - val arraySize = elements.size - val result = copyOfUninitializedElements(thisSize + arraySize) - elements.copyRangeTo(result, 0, arraySize, thisSize) - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] array. - */ -public operator fun ByteArray.plus(elements: ByteArray): ByteArray { - val thisSize = size - val arraySize = elements.size - val result = copyOfUninitializedElements(thisSize + arraySize) - elements.copyRangeTo(result, 0, arraySize, thisSize) - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] array. - */ -public operator fun ShortArray.plus(elements: ShortArray): ShortArray { - val thisSize = size - val arraySize = elements.size - val result = copyOfUninitializedElements(thisSize + arraySize) - elements.copyRangeTo(result, 0, arraySize, thisSize) - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] array. - */ -public operator fun IntArray.plus(elements: IntArray): IntArray { - val thisSize = size - val arraySize = elements.size - val result = copyOfUninitializedElements(thisSize + arraySize) - elements.copyRangeTo(result, 0, arraySize, thisSize) - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] array. - */ -public operator fun LongArray.plus(elements: LongArray): LongArray { - val thisSize = size - val arraySize = elements.size - val result = copyOfUninitializedElements(thisSize + arraySize) - elements.copyRangeTo(result, 0, arraySize, thisSize) - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] array. - */ -public operator fun FloatArray.plus(elements: FloatArray): FloatArray { - val thisSize = size - val arraySize = elements.size - val result = copyOfUninitializedElements(thisSize + arraySize) - elements.copyRangeTo(result, 0, arraySize, thisSize) - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] array. - */ -public operator fun DoubleArray.plus(elements: DoubleArray): DoubleArray { - val thisSize = size - val arraySize = elements.size - val result = copyOfUninitializedElements(thisSize + arraySize) - elements.copyRangeTo(result, 0, arraySize, thisSize) - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] array. - */ -public operator fun BooleanArray.plus(elements: BooleanArray): BooleanArray { - val thisSize = size - val arraySize = elements.size - val result = copyOfUninitializedElements(thisSize + arraySize) - elements.copyRangeTo(result, 0, arraySize, thisSize) - return result -} - -/** - * Returns an array containing all elements of the original array and then all elements of the given [elements] array. - */ -public operator fun CharArray.plus(elements: CharArray): CharArray { - val thisSize = size - val arraySize = elements.size - val result = copyOfUninitializedElements(thisSize + arraySize) - elements.copyRangeTo(result, 0, arraySize, thisSize) - return result -} - -/** - * Returns an array containing all elements of the original array and then the given [element]. - */ -@kotlin.internal.InlineOnly -public inline fun Array.plusElement(element: T): Array { - return plus(element) -} diff --git a/runtime/src/main/kotlin/kotlin/Comparable.kt b/runtime/src/main/kotlin/kotlin/Comparable.kt index 9a489f55524..4262d3aa638 100644 --- a/runtime/src/main/kotlin/kotlin/Comparable.kt +++ b/runtime/src/main/kotlin/kotlin/Comparable.kt @@ -16,7 +16,7 @@ package kotlin -import kotlin.comparisons.Comparator +import kotlin.Comparator /** * Classes which inherit from this interface have a defined total ordering between their instances. diff --git a/runtime/src/main/kotlin/kotlin/collections/IndexedValue.kt b/runtime/src/main/kotlin/kotlin/Comparator.kt similarity index 58% rename from runtime/src/main/kotlin/kotlin/collections/IndexedValue.kt rename to runtime/src/main/kotlin/kotlin/Comparator.kt index 4eace943c73..38558de9122 100644 --- a/runtime/src/main/kotlin/kotlin/collections/IndexedValue.kt +++ b/runtime/src/main/kotlin/kotlin/Comparator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. + * Copyright 2010-2018 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. @@ -14,12 +14,14 @@ * limitations under the License. */ -package kotlin.collections +package kotlin -/** - * Data class representing a value from a collection or sequence, along with its index in that collection or sequence. - * - * @property value the underlying value. - * @property index the index of the value in the collection or sequence. - */ -public data class IndexedValue(public val index: Int, public val value: T) +actual interface Comparator { + actual fun compare(a: T, b: T): Int +} + +actual inline fun Comparator(crossinline comparison: (a: T, b: T) -> Int): Comparator { + return object: Comparator { + override fun compare(a: T, b: T) = comparison(a, b) + } +} \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/Exceptions.kt b/runtime/src/main/kotlin/kotlin/Exceptions.kt index 834c2973636..73aef785d00 100644 --- a/runtime/src/main/kotlin/kotlin/Exceptions.kt +++ b/runtime/src/main/kotlin/kotlin/Exceptions.kt @@ -16,162 +16,170 @@ package kotlin -public open class Error : Throwable { +public actual open class Error : Throwable { - constructor() : super() + actual constructor() : super() - constructor(message: String?) : super(message) + actual constructor(message: String?) : super(message) - constructor(message: String?, cause: Throwable?) : super(message, cause) + actual constructor(message: String?, cause: Throwable?) : super(message, cause) - constructor(cause: Throwable?) : super(cause) + actual constructor(cause: Throwable?) : super(cause) } -public open class Exception : Throwable { +public actual open class Exception : Throwable { - constructor() : super() + actual constructor() : super() - constructor(message: String?) : super(message) + actual constructor(message: String?) : super(message) - constructor(message: String?, cause: Throwable?) : super(message, cause) + actual constructor(message: String?, cause: Throwable?) : super(message, cause) - constructor(cause: Throwable?) : super(cause) + actual constructor(cause: Throwable?) : super(cause) } -public open class RuntimeException : Exception { +public actual open class RuntimeException : Exception { - constructor() : super() + actual constructor() : super() - constructor(message: String?) : super(message) + actual constructor(message: String?) : super(message) - constructor(message: String?, cause: Throwable?) : super(message, cause) + actual constructor(message: String?, cause: Throwable?) : super(message, cause) - constructor(cause: Throwable?) : super(cause) + actual constructor(cause: Throwable?) : super(cause) } -public class NullPointerException : RuntimeException { +public actual open class NullPointerException : RuntimeException { - constructor() : super() + actual constructor() : super() - constructor(s: String?) : super(s) + actual constructor(message: String?) : super(message) } -public open class NoSuchElementException : RuntimeException { +public actual open class NoSuchElementException : RuntimeException { - constructor() : super() + actual constructor() : super() - constructor(s: String?) : super(s) + actual constructor(message: String?) : super(message) } -public open class IllegalArgumentException : RuntimeException { +public actual open class IllegalArgumentException : RuntimeException { - constructor() : super() + actual constructor() : super() - constructor(s: String?) : super(s) + actual constructor(message: String?) : super(message) - constructor(message: String?, cause: Throwable?) : super(message, cause) + actual constructor(message: String?, cause: Throwable?) : super(message, cause) - constructor(cause: Throwable?) : super(cause) + actual constructor(cause: Throwable?) : super(cause) } -public open class IllegalStateException : RuntimeException { +public actual open class IllegalStateException : RuntimeException { - constructor() : super() + actual constructor() : super() - constructor(s: String?) : super(s) + actual constructor(message: String?) : super(message) - constructor(message: String?, cause: Throwable?) : super(message, cause) + actual constructor(message: String?, cause: Throwable?) : super(message, cause) - constructor(cause: Throwable?) : super(cause) + actual constructor(cause: Throwable?) : super(cause) } -public open class UnsupportedOperationException : RuntimeException { +public actual open class UnsupportedOperationException : RuntimeException { - constructor() + actual constructor() - constructor(message: String?) : super(message) + actual constructor(message: String?) : super(message) - constructor(message: String?, cause: Throwable?) : super(message, cause) + actual constructor(message: String?, cause: Throwable?) : super(message, cause) - constructor(cause: Throwable?) : super(cause) + actual constructor(cause: Throwable?) : super(cause) } -public open class IndexOutOfBoundsException : RuntimeException { +public actual open class IndexOutOfBoundsException : RuntimeException { - constructor() : super() + actual constructor() : super() - constructor(s: String?) : super(s) + actual constructor(message: String?) : super(message) } public open class ArrayIndexOutOfBoundsException : IndexOutOfBoundsException { constructor() : super() - constructor(s: String?) : super(s) + constructor(message: String?) : super(message) } -public open class ClassCastException : RuntimeException { +public actual open class ClassCastException : RuntimeException { - constructor() : super() + actual constructor() : super() - constructor(s: String?) : super(s) + actual constructor(message: String?) : super(message) } public open class TypeCastException : ClassCastException { constructor() : super() - constructor(s: String?) : super(s) + constructor(message: String?) : super(message) } public open class ArithmeticException : RuntimeException { constructor() : super() - constructor(s: String?) : super(s) + constructor(message: String?) : super(message) } -public open class AssertionError : Error { +public actual open class AssertionError : Error { - constructor() + actual constructor() constructor(message: String?) : super(message) - constructor(message: Any?) : super(message.toString()) + actual constructor(message: Any?) : super(message.toString()) constructor(message: String?, cause: Throwable?) : super(message, cause) } -public open class NoWhenBranchMatchedException : RuntimeException { +public actual open class NoWhenBranchMatchedException : RuntimeException { - constructor() : super() + actual constructor() : super() - constructor(s: String?) : super(s) + actual constructor(message: String?) : super(message) + + actual constructor(message: String?, cause: Throwable?) : super(message, cause) + + actual constructor(cause: Throwable?) : super(cause) } -public open class UninitializedPropertyAccessException : RuntimeException { +public actual open class UninitializedPropertyAccessException : RuntimeException { - constructor() : super() + actual constructor() : super() - constructor(s: String?) : super(s) + actual constructor(message: String?) : super(message) + + actual constructor(message: String?, cause: Throwable?) : super(message, cause) + + actual constructor(cause: Throwable?) : super(cause) } public open class OutOfMemoryError : Error { constructor() : super() - constructor(s: String?) : super(s) + constructor(message: String?) : super(message) } -public open class NumberFormatException : IllegalArgumentException { +public actual open class NumberFormatException : IllegalArgumentException { - constructor() : super() + actual constructor() : super() - constructor(s: String?) : super(s) + actual constructor(message: String?) : super(message) } public open class IllegalCharacterConversionException : IllegalArgumentException { constructor(): super() - constructor(s: String?) : super(s) + constructor(message: String?) : super(message) } \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/KotlinVersion.kt b/runtime/src/main/kotlin/kotlin/KotlinVersion.kt deleted file mode 100644 index c1363ca2670..00000000000 --- a/runtime/src/main/kotlin/kotlin/KotlinVersion.kt +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin - -/** - * Represents a version of the Kotlin standard library. - * - * [major], [minor] and [patch] are integer components of a version, - * they must be non-negative and not greater than 255 ([MAX_COMPONENT_VALUE]). - * - * @constructor Creates a version from all three components. - */ -public class KotlinVersion(val major: Int, val minor: Int, val patch: Int) : Comparable { - /** - * Creates a version from [major] and [minor] components, leaving [patch] component zero. - */ - public constructor(major: Int, minor: Int) : this(major, minor, 0) - - private val version = versionOf(major, minor, patch) - - private fun versionOf(major: Int, minor: Int, patch: Int): Int { - require(major in 0..MAX_COMPONENT_VALUE && minor in 0..MAX_COMPONENT_VALUE && patch in 0..MAX_COMPONENT_VALUE) { - "Version components are out of range: $major.$minor.$patch" - } - return major.shl(16) + minor.shl(8) + patch - } - - /** - * Returns the string representation of this version - */ - override fun toString(): String = "$major.$minor.$patch" - - override fun equals(other: Any?): Boolean { - if (this === other) return true - val otherVersion = (other as? KotlinVersion) ?: return false - return this.version == otherVersion.version - } - - override fun hashCode(): Int = version - - override fun compareTo(other: KotlinVersion): Int = version - other.version - - /** - * Returns `true` if this version is not less than the version specified - * with the provided [major] and [minor] components. - */ - public fun isAtLeast(major: Int, minor: Int): Boolean = - // or this.version >= versionOf(major, minor, 0) - this.major > major || (this.major == major && - this.minor >= minor) - - /** - * Returns `true` if this version is not less than the version specified - * with the provided [major], [minor] and [patch] components. - */ - public fun isAtLeast(major: Int, minor: Int, patch: Int): Boolean = - // or this.version >= versionOf(major, minor, patch) - this.major > major || (this.major == major && - (this.minor > minor || this.minor == minor && - this.patch >= patch)) - - companion object { - /** - * Maximum value a version component can have, a constant value 255. - */ - // NOTE: Must be placed before CURRENT because its initialization requires this field being initialized in JS - public const val MAX_COMPONENT_VALUE = 255 - - /** - * Returns the current version of the Kotlin standard library. - */ - // TODO: get from metadata or hardcode automatically during build - public val CURRENT: KotlinVersion = KotlinVersion(1, 2, 0) - } -} diff --git a/runtime/src/main/kotlin/kotlin/Lazy.kt b/runtime/src/main/kotlin/kotlin/Lazy.kt index 2fb3e16d682..1ff38677c0a 100644 --- a/runtime/src/main/kotlin/kotlin/Lazy.kt +++ b/runtime/src/main/kotlin/kotlin/Lazy.kt @@ -18,29 +18,6 @@ package kotlin import kotlin.reflect.KProperty -/** - * Represents a value with lazy initialization. - * - * To create an instance of [Lazy] use the [lazy] function. - */ -public interface Lazy { - /** - * Gets the lazily initialized value of the current Lazy instance. - * Once the value was initialized it must not change during the rest of lifetime of this Lazy instance. - */ - public val value: T - /** - * Returns `true` if a value for this Lazy instance has been already initialized, and `false` otherwise. - * Once this function has returned `true` it stays `true` for the rest of lifetime of this Lazy instance. - */ - public fun isInitialized(): Boolean -} - -/** - * Creates a new instance of the [Lazy] that is already initialized with the specified [value]. - */ -public fun lazyOf(value: T): Lazy = InitializedLazyImpl(value) - /** * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] * and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED]. @@ -51,7 +28,7 @@ public fun lazyOf(value: T): Lazy = InitializedLazyImpl(value) * the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future. */ @FixmeConcurrency -public fun lazy(initializer: () -> T): Lazy = UnsafeLazyImpl(initializer)//SynchronizedLazyImpl(initializer) +public actual fun lazy(initializer: () -> T): Lazy = UnsafeLazyImpl(initializer)//SynchronizedLazyImpl(initializer) /** * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer] @@ -64,7 +41,7 @@ public fun lazy(initializer: () -> T): Lazy = UnsafeLazyImpl(initializer) * Also this behavior can be changed in the future. */ @FixmeConcurrency -public fun lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy = +public actual fun lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy = when (mode) { LazyThreadSafetyMode.SYNCHRONIZED -> TODO()//SynchronizedLazyImpl(initializer) LazyThreadSafetyMode.PUBLICATION -> TODO()//SafePublicationLazyImpl(initializer) @@ -84,140 +61,4 @@ public fun lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy = */ @FixmeConcurrency @Suppress("UNUSED_PARAMETER") -public fun lazy(lock: Any?, initializer: () -> T): Lazy = TODO()//SynchronizedLazyImpl(initializer, lock) - -/** - * An extension to delegate a read-only property of type [T] to an instance of [Lazy]. - * - * This extension allows to use instances of Lazy for property delegation: - * `val property: String by lazy { initializer }` - */ -@kotlin.internal.InlineOnly -public inline operator fun Lazy.getValue(thisRef: Any?, property: KProperty<*>): T = value - -/** - * Specifies how a [Lazy] instance synchronizes access among multiple threads. - */ -public enum class LazyThreadSafetyMode { - - /** - * Locks are used to ensure that only a single thread can initialize the [Lazy] instance. - */ - SYNCHRONIZED, - - /** - * Initializer function can be called several times on concurrent access to uninitialized [Lazy] instance value, - * but only first returned value will be used as the value of [Lazy] instance. - */ - PUBLICATION, - - /** - * No locks are used to synchronize the access to the [Lazy] instance value; if the instance is accessed from multiple threads, its behavior is undefined. - * - * This mode should be used only when high performance is crucial and the [Lazy] instance is guaranteed never to be initialized from more than one thread. - */ - NONE, -} - - -private object UNINITIALIZED_VALUE - -//private class SynchronizedLazyImpl(initializer: () -> T, lock: Any? = null) : Lazy, Serializable { -// private var initializer: (() -> T)? = initializer -// @Volatile private var _value: Any? = UNINITIALIZED_VALUE -// // final field is required to enable safe publication of constructed instance -// private val lock = lock ?: this -// -// override val value: T -// get() { -// val _v1 = _value -// if (_v1 !== UNINITIALIZED_VALUE) { -// @Suppress("UNCHECKED_CAST") -// return _v1 as T -// } -// -// return synchronized(lock) { -// val _v2 = _value -// if (_v2 !== UNINITIALIZED_VALUE) { -// @Suppress("UNCHECKED_CAST") (_v2 as T) -// } -// else { -// val typedValue = initializer!!() -// _value = typedValue -// initializer = null -// typedValue -// } -// } -// } -// -// override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE -// -// override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet." -// -// private fun writeReplace(): Any = InitializedLazyImpl(value) -//} - -internal class UnsafeLazyImpl(initializer: () -> T) : Lazy/*, Serializable*/ { - private var initializer: (() -> T)? = initializer - private var _value: Any? = UNINITIALIZED_VALUE - - override val value: T - get() { - if (_value === UNINITIALIZED_VALUE) { - _value = initializer!!() - initializer = null - } - @Suppress("UNCHECKED_CAST") - return _value as T - } - - override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE - - override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet." - - private fun writeReplace(): Any = InitializedLazyImpl(value) -} - -private class InitializedLazyImpl(override val value: T) : Lazy/*, Serializable*/ { - - override fun isInitialized(): Boolean = true - - override fun toString(): String = value.toString() - -} - -//private class SafePublicationLazyImpl(initializer: () -> T) : Lazy, Serializable { -// private var initializer: (() -> T)? = initializer -// @Volatile private var _value: Any? = UNINITIALIZED_VALUE -// // this final field is required to enable safe publication of constructed instance -// private val final: Any = UNINITIALIZED_VALUE -// -// override val value: T -// get() { -// if (_value === UNINITIALIZED_VALUE) { -// val initializerValue = initializer -// // if we see null in initializer here, it means that the value is already set by another thread -// if (initializerValue != null) { -// val newValue = initializerValue() -// if (valueUpdater.compareAndSet(this, UNINITIALIZED_VALUE, newValue)) { -// initializer = null -// } -// } -// } -// @Suppress("UNCHECKED_CAST") -// return _value as T -// } -// -// override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE -// -// override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet." -// -// private fun writeReplace(): Any = InitializedLazyImpl(value) -// -// companion object { -// private val valueUpdater = java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater( -// SafePublicationLazyImpl::class.java, -// Any::class.java, -// "_value") -// } -//} \ No newline at end of file +public actual fun lazy(lock: Any?, initializer: () -> T): Lazy = TODO()//SynchronizedLazyImpl(initializer, lock) diff --git a/runtime/src/main/kotlin/kotlin/Numbers.kt b/runtime/src/main/kotlin/kotlin/Numbers.kt index 006b813dd61..7b574804ebd 100644 --- a/runtime/src/main/kotlin/kotlin/Numbers.kt +++ b/runtime/src/main/kotlin/kotlin/Numbers.kt @@ -21,38 +21,38 @@ package kotlin * Not-a-Number (NaN) value, `false` otherwise. */ @SymbolName("Kotlin_Double_isNaN") -external public fun Double.isNaN(): Boolean +external public actual fun Double.isNaN(): Boolean /** * Returns `true` if the specified number is a * Not-a-Number (NaN) value, `false` otherwise. */ @SymbolName("Kotlin_Float_isNaN") -external public fun Float.isNaN(): Boolean +external public actual fun Float.isNaN(): Boolean /** * Returns `true` if this value is infinitely large in magnitude. */ @SymbolName("Kotlin_Double_isInfinite") -external public fun Double.isInfinite(): Boolean +external public actual fun Double.isInfinite(): Boolean /** * Returns `true` if this value is infinitely large in magnitude. */ @SymbolName("Kotlin_Float_isInfinite") -external public fun Float.isInfinite(): Boolean +external public actual fun Float.isInfinite(): Boolean /** * Returns `true` if the argument is a finite floating-point value; returns `false` otherwise (for `NaN` and infinity arguments). */ @SymbolName("Kotlin_Double_isFinite") -external public fun Double.isFinite(): Boolean +external public actual fun Double.isFinite(): Boolean /** * Returns `true` if the argument is a finite floating-point value; returns `false` otherwise (for `NaN` and infinity arguments). */ @SymbolName("Kotlin_Float_isFinite") -external public fun Float.isFinite(): Boolean +external public actual fun Float.isFinite(): Boolean /** * Returns a bit representation of the specified floating-point value as [Long] @@ -60,7 +60,7 @@ external public fun Float.isFinite(): Boolean */ @SinceKotlin("1.2") @kotlin.internal.InlineOnly -public inline fun Double.toBits(): Long = if (isNaN()) Double.NaN.toRawBits() else toRawBits() +public actual inline fun Double.toBits(): Long = if (isNaN()) Double.NaN.toRawBits() else toRawBits() /** * Returns a bit representation of the specified floating-point value as [Long] @@ -69,14 +69,14 @@ public inline fun Double.toBits(): Long = if (isNaN()) Double.NaN.toRawBits() el */ @SinceKotlin("1.2") @kotlin.internal.InlineOnly -public inline fun Double.toRawBits(): Long = bits() +public actual inline fun Double.toRawBits(): Long = bits() /** * Returns the [Double] value corresponding to a given bit representation. */ @SinceKotlin("1.2") @kotlin.internal.InlineOnly -public inline fun Double.Companion.fromBits(bits: Long): Double = kotlin.fromBits(bits) +public actual inline fun Double.Companion.fromBits(bits: Long): Double = kotlin.fromBits(bits) @PublishedApi @SymbolName("Kotlin_Double_fromBits") @@ -88,7 +88,7 @@ external internal fun fromBits(bits: Long): Double */ @SinceKotlin("1.2") @kotlin.internal.InlineOnly -public inline fun Float.toBits(): Int = if (isNaN()) Float.NaN.toRawBits() else toRawBits() +public actual inline fun Float.toBits(): Int = if (isNaN()) Float.NaN.toRawBits() else toRawBits() /** * Returns a bit representation of the specified floating-point value as [Int] @@ -97,14 +97,14 @@ public inline fun Float.toBits(): Int = if (isNaN()) Float.NaN.toRawBits() else */ @SinceKotlin("1.2") @kotlin.internal.InlineOnly -public inline fun Float.toRawBits(): Int = bits() +public actual inline fun Float.toRawBits(): Int = bits() /** * Returns the [Float] value corresponding to a given bit representation. */ @SinceKotlin("1.2") @kotlin.internal.InlineOnly -public inline fun Float.Companion.fromBits(bits: Int): Float = kotlin.fromBits(bits) +public actual inline fun Float.Companion.fromBits(bits: Int): Float = kotlin.fromBits(bits) @PublishedApi @SymbolName("Kotlin_Float_fromBits") diff --git a/runtime/src/main/kotlin/kotlin/collections/AbstractIterator.kt b/runtime/src/main/kotlin/kotlin/collections/AbstractIterator.kt deleted file mode 100644 index 2a065439cd4..00000000000 --- a/runtime/src/main/kotlin/kotlin/collections/AbstractIterator.kt +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.collections - - -private enum class State { - Ready, - NotReady, - Done, - Failed -} - -/** - * A base class to simplify implementing iterators so that implementations only have to implement [computeNext] - * to implement the iterator, calling [done] when the iteration is complete. - */ -public abstract class AbstractIterator: Iterator { - private var state = State.NotReady - private var nextValue: T? = null - - override fun hasNext(): Boolean { - require(state != State.Failed) - return when (state) { - State.Done -> false - State.Ready -> true - else -> tryToComputeNext() - } - } - - override fun next(): T { - if (!hasNext()) throw NoSuchElementException() - state = State.NotReady - @Suppress("UNCHECKED_CAST") - return nextValue as T - } - - private fun tryToComputeNext(): Boolean { - state = State.Failed - computeNext() - return state == State.Ready - } - - /** - * Computes the next item in the iterator. - * - * This callback method should call one of these two methods: - * - * * [setNext] with the next value of the iteration - * * [done] to indicate there are no more elements - * - * Failure to call either method will result in the iteration terminating with a failed state - */ - abstract protected fun computeNext(): Unit - - /** - * Sets the next value in the iteration, called from the [computeNext] function - */ - protected fun setNext(value: T): Unit { - nextValue = value - state = State.Ready - } - - /** - * Sets the state to done so that the iteration terminates. - */ - protected fun done() { - state = State.Done - } -} - - diff --git a/runtime/src/main/kotlin/kotlin/collections/AbstractCollection.kt b/runtime/src/main/kotlin/kotlin/collections/AbstractMutableCollection.kt similarity index 68% rename from runtime/src/main/kotlin/kotlin/collections/AbstractCollection.kt rename to runtime/src/main/kotlin/kotlin/collections/AbstractMutableCollection.kt index e185bdd0991..31604e646f8 100644 --- a/runtime/src/main/kotlin/kotlin/collections/AbstractCollection.kt +++ b/runtime/src/main/kotlin/kotlin/collections/AbstractMutableCollection.kt @@ -16,40 +16,6 @@ package kotlin.collections -/** - * Provides a skeletal implementation of the read-only [Collection] interface. - * - * @param E the type of elements contained in the collection. The collection is covariant on its element type. - */ -@SinceKotlin("1.1") -public abstract class AbstractCollection protected constructor() : Collection { - abstract override val size: Int - abstract override fun iterator(): Iterator - - override fun contains(element: @UnsafeVariance E): Boolean = any { it == element } - - override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean = - elements.all { contains(it) } - - override fun isEmpty(): Boolean = size == 0 - - - override fun toString(): String = joinToString(", ", "[", "]") { - if (it === this) "(this Collection)" else it.toString() - } - - /** - * Returns new array of type `Array` with the elements of this collection. - */ - protected open fun toArray(): Array = collectionToArray(this) - - /** - * Fills the provided [array] or creates new array of the same type - * and fills it with the elements of this collection. - */ - protected open fun toArray(array: Array): Array = collectionToArray(this, array) -} - public abstract class AbstractMutableCollection protected constructor(): MutableCollection, AbstractCollection() { // Bulk Modification Operations diff --git a/runtime/src/main/kotlin/kotlin/collections/AbstractList.kt b/runtime/src/main/kotlin/kotlin/collections/AbstractMutableList.kt similarity index 52% rename from runtime/src/main/kotlin/kotlin/collections/AbstractList.kt rename to runtime/src/main/kotlin/kotlin/collections/AbstractMutableList.kt index 30705c43884..ddff4188ae1 100644 --- a/runtime/src/main/kotlin/kotlin/collections/AbstractList.kt +++ b/runtime/src/main/kotlin/kotlin/collections/AbstractMutableList.kt @@ -15,131 +15,6 @@ */ package kotlin.collections -public abstract class AbstractList protected constructor() : AbstractCollection(), List { - abstract override val size: Int - abstract override fun get(index: Int): E - - override fun iterator(): Iterator = IteratorImpl() - - override fun indexOf(element: @UnsafeVariance E): Int = indexOfFirst { it == element } - - override fun lastIndexOf(element: @UnsafeVariance E): Int = indexOfLast { it == element } - - override fun listIterator(): ListIterator = ListIteratorImpl(0) - - override fun listIterator(index: Int): ListIterator = ListIteratorImpl(index) - - override fun subList(fromIndex: Int, toIndex: Int): List = SubList(this, fromIndex, toIndex) - - internal open class SubList( - private val list: AbstractList, private val fromIndex: Int, toIndex: Int) : AbstractList() { - private var _size: Int = 0 - - init { - checkRangeIndexes(fromIndex, toIndex, list.size) - this._size = toIndex - fromIndex - } - - override fun get(index: Int): E { - checkElementIndex(index, _size) - - return list[fromIndex + index] - } - - override val size: Int get() = _size - } - - override fun equals(other: Any?): Boolean { - if (other === this) return true - if (other !is List<*>) return false - - return orderedEquals(this, other) - } - - override fun hashCode(): Int = orderedHashCode(this) - - - private open inner class IteratorImpl : Iterator { - /** the index of the item that will be returned on the next call to [next]`()` */ - protected var index = 0 - - override fun hasNext(): Boolean = index < size - - override fun next(): E { - if (!hasNext()) throw NoSuchElementException() - return get(index++) - } - } - - /** - * Implementation of `MutableListIterator` for abstract lists. - */ - private open inner class ListIteratorImpl(index: Int) : IteratorImpl(), ListIterator { - - init { - checkPositionIndex(index, this@AbstractList.size) - this.index = index - } - - override fun hasPrevious(): Boolean = index > 0 - - override fun nextIndex(): Int = index - - override fun previous(): E { - if (!hasPrevious()) throw NoSuchElementException() - return get(--index) - } - - override fun previousIndex(): Int = index - 1 - } - - internal companion object { - internal fun checkElementIndex(index: Int, size: Int) { - if (index < 0 || index >= size) { - throw IndexOutOfBoundsException("index: $index, size: $size") - } - } - - internal fun checkPositionIndex(index: Int, size: Int) { - if (index < 0 || index > size) { - throw IndexOutOfBoundsException("index: $index, size: $size") - } - } - - internal fun checkRangeIndexes(start: Int, end: Int, size: Int) { - if (start < 0 || end > size) { - throw IndexOutOfBoundsException("fromIndex: $start, toIndex: $end, size: $size") - } - if (start > end) { - throw IllegalArgumentException("fromIndex: $start > toIndex: $end") - } - } - - internal fun orderedHashCode(c: Collection<*>): Int { - var hashCode = 1 - for (e in c) { - hashCode = 31 * hashCode + (if (e != null) e.hashCode() else 0) - hashCode = hashCode or 0 // make sure we don't overflow - } - return hashCode - } - - internal fun orderedEquals(c: Collection<*>, other: Collection<*>): Boolean { - if (c.size != other.size) return false - - val otherIterator = other.iterator() - for (elem in c) { - val elemOther = otherIterator.next() - if (elem != elemOther) { - return false - } - } - return true - } - } -} - - /** * AbstractMutableList implementation copied from JS backend * (see js/js.libraries/src/core/collections/AbstractMutableList.kt). @@ -153,19 +28,19 @@ public abstract class AbstractList protected constructor() : AbstractColl * * @param E the type of elements contained in the list. The list is invariant on its element type. */ -public abstract class AbstractMutableList protected constructor() : AbstractMutableCollection(), MutableList { +public actual abstract class AbstractMutableList protected actual constructor() : AbstractMutableCollection(), MutableList { protected var modCount: Int = 0 abstract override fun add(index: Int, element: E): Unit abstract override fun removeAt(index: Int): E abstract override fun set(index: Int, element: E): E - override fun add(element: E): Boolean { + override actual fun add(element: E): Boolean { add(size, element) return true } - override fun addAll(index: Int, elements: Collection): Boolean { + override actual fun addAll(index: Int, elements: Collection): Boolean { var i = index var changed = false for (e in elements) { @@ -175,19 +50,19 @@ public abstract class AbstractMutableList protected constructor() : AbstractM return changed } - override fun clear() { + override actual fun clear() { removeRange(0, size) } - override fun removeAll(elements: Collection): Boolean = removeAll { it in elements } - override fun retainAll(elements: Collection): Boolean = removeAll { it !in elements } + override actual fun removeAll(elements: Collection): Boolean = removeAll { it in elements } + override actual fun retainAll(elements: Collection): Boolean = removeAll { it !in elements } - override fun iterator(): MutableIterator = IteratorImpl() + override actual fun iterator(): MutableIterator = IteratorImpl() - override fun contains(element: E): Boolean = indexOf(element) >= 0 + override actual fun contains(element: E): Boolean = indexOf(element) >= 0 - override fun indexOf(element: E): Int { + override actual fun indexOf(element: E): Int { for (index in 0..lastIndex) { if (get(index) == element) { return index @@ -196,7 +71,7 @@ public abstract class AbstractMutableList protected constructor() : AbstractM return -1 } - override fun lastIndexOf(element: E): Int { + override actual fun lastIndexOf(element: E): Int { for (index in lastIndex downTo 0) { if (get(index) == element) { return index @@ -205,11 +80,11 @@ public abstract class AbstractMutableList protected constructor() : AbstractM return -1 } - override fun listIterator(): MutableListIterator = listIterator(0) - override fun listIterator(index: Int): MutableListIterator = ListIteratorImpl(index) + override actual fun listIterator(): MutableListIterator = listIterator(0) + override actual fun listIterator(index: Int): MutableListIterator = ListIteratorImpl(index) - override fun subList(fromIndex: Int, toIndex: Int): MutableList = SubList(this, fromIndex, toIndex) + override actual fun subList(fromIndex: Int, toIndex: Int): MutableList = SubList(this, fromIndex, toIndex) /** * Removes the range of elements from this list starting from [fromIndex] and ending with but not including [toIndex]. diff --git a/runtime/src/main/kotlin/kotlin/collections/AbstractSet.kt b/runtime/src/main/kotlin/kotlin/collections/AbstractSet.kt deleted file mode 100644 index 500ab16f95d..00000000000 --- a/runtime/src/main/kotlin/kotlin/collections/AbstractSet.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2010-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 kotlin.collections - -/** - * Provides a skeletal implementation of the read-only [Set] interface. - * - * This class is intended to help implementing read-only sets so it doesn't support concurrent modification tracking. - * - * @param E the type of elements contained in the set. The set is covariant on its element type. - */ -@SinceKotlin("1.1") -public abstract class AbstractSet protected constructor() : AbstractCollection(), Set { - - /** - * Compares this set with other set instance with the unordered structural equality. - * - * @return true, if [other] instance is a [Set] of the same size, all elements of which are contained in this set. - */ - override fun equals(other: Any?): Boolean { - if (other === this) return true - if (other !is Set<*>) return false - return setEquals(this, other) - } - - /** - * Returns the hash code value for this set. - */ - override fun hashCode(): Int = unorderedHashCode(this) - - internal companion object { - internal fun unorderedHashCode(c: Collection<*>): Int { - var hashCode = 0 - for (element in c) { - hashCode += (element?.hashCode() ?: 0) - } - return hashCode - } - - internal fun setEquals(c: Set<*>, other: Set<*>): Boolean { - if (c.size != other.size) return false - return c.containsAll(other) - } - } - -} \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/collections/ArrayList.kt b/runtime/src/main/kotlin/kotlin/collections/ArrayList.kt index f972180eba7..9838b3737dc 100644 --- a/runtime/src/main/kotlin/kotlin/collections/ArrayList.kt +++ b/runtime/src/main/kotlin/kotlin/collections/ArrayList.kt @@ -16,40 +16,40 @@ package kotlin.collections -class ArrayList private constructor( +actual class ArrayList private constructor( private var array: Array, private var offset: Int, private var length: Int, private val backing: ArrayList? ) : MutableList, RandomAccess, AbstractMutableCollection() { - constructor() : this(10) + actual constructor() : this(10) - constructor(initialCapacity: Int) : this( + actual constructor(initialCapacity: Int) : this( arrayOfUninitializedElements(initialCapacity), 0, 0, null) - constructor(c: Collection) : this(c.size) { - addAll(c) + actual constructor(elements: Collection) : this(elements.size) { + addAll(elements) } - override val size : Int + override actual val size : Int get() = length - override fun isEmpty(): Boolean = length == 0 + override actual fun isEmpty(): Boolean = length == 0 - override fun get(index: Int): E { + override actual fun get(index: Int): E { checkIndex(index) return array[offset + index] } - override fun set(index: Int, element: E): E { + override actual operator fun set(index: Int, element: E): E { checkIndex(index) val old = array[offset + index] array[offset + index] = element return old } - override fun contains(element: E): Boolean { + override actual fun contains(element: E): Boolean { var i = 0 while (i < length) { if (array[offset + i] == element) return true @@ -58,7 +58,7 @@ class ArrayList private constructor( return false } - override fun containsAll(elements: Collection): Boolean { + override actual fun containsAll(elements: Collection): Boolean { val it = elements.iterator() while (it.hasNext()) { if (!contains(it.next()))return false @@ -66,7 +66,7 @@ class ArrayList private constructor( return true } - override fun indexOf(element: E): Int { + override actual fun indexOf(element: E): Int { var i = 0 while (i < length) { if (array[offset + i] == element) return i @@ -75,7 +75,7 @@ class ArrayList private constructor( return -1 } - override fun lastIndexOf(element: E): Int { + override actual fun lastIndexOf(element: E): Int { var i = length - 1 while (i >= 0) { if (array[offset + i] == element) return i @@ -84,78 +84,78 @@ class ArrayList private constructor( return -1 } - override fun iterator(): MutableIterator = Itr(this, 0) - override fun listIterator(): MutableListIterator = Itr(this, 0) + override actual fun iterator(): MutableIterator = Itr(this, 0) + override actual fun listIterator(): MutableListIterator = Itr(this, 0) - override fun listIterator(index: Int): MutableListIterator { + override actual fun listIterator(index: Int): MutableListIterator { checkInsertIndex(index) return Itr(this, index) } - override fun add(element: E): Boolean { + override actual fun add(element: E): Boolean { addAtInternal(offset + length, element) return true } - override fun add(index: Int, element: E) { + override actual fun add(index: Int, element: E) { checkInsertIndex(index) addAtInternal(offset + index, element) } - override fun addAll(elements: Collection): Boolean { + override actual fun addAll(elements: Collection): Boolean { val n = elements.size addAllInternal(offset + length, elements, n) return n > 0 } - override fun addAll(index: Int, elements: Collection): Boolean { + override actual fun addAll(index: Int, elements: Collection): Boolean { checkInsertIndex(index) val n = elements.size addAllInternal(offset + index, elements, n) return n > 0 } - override fun clear() { + override actual fun clear() { removeRangeInternal(offset, length) } - override fun removeAt(index: Int): E { + override actual fun removeAt(index: Int): E { checkIndex(index) return removeAtInternal(offset + index) } - override fun remove(element: E): Boolean { + override actual fun remove(element: E): Boolean { val i = indexOf(element) if (i >= 0) removeAt(i) return i >= 0 } - override fun removeAll(elements: Collection): Boolean { + override actual fun removeAll(elements: Collection): Boolean { return retainOrRemoveAllInternal(offset, length, elements, false) > 0 } - override fun retainAll(elements: Collection): Boolean { + override actual fun retainAll(elements: Collection): Boolean { return retainOrRemoveAllInternal(offset, length, elements, true) > 0 } - override fun subList(fromIndex: Int, toIndex: Int): MutableList { + override actual fun subList(fromIndex: Int, toIndex: Int): MutableList { checkInsertIndex(fromIndex) checkInsertIndexFrom(toIndex, fromIndex) return ArrayList(array, offset + fromIndex, toIndex - fromIndex, this) } - fun trimToSize() { + actual fun trimToSize() { if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ArrayList if (length < array.size) array = array.copyOfUninitializedElements(length) } - fun ensureCapacity(capacity: Int) { + final actual fun ensureCapacity(minCapacity: Int) { if (backing != null) throw IllegalStateException() // just in case somebody casts subList to ArrayList - if (capacity > array.size) { + if (minCapacity > array.size) { var newSize = array.size * 3 / 2 - if (capacity > newSize) - newSize = capacity + if (minCapacity > newSize) + newSize = minCapacity array = array.copyOfUninitializedElements(newSize) } } diff --git a/runtime/src/main/kotlin/kotlin/collections/Arrays.kt b/runtime/src/main/kotlin/kotlin/collections/Arrays.kt index ac128edead7..61a3b2904f7 100644 --- a/runtime/src/main/kotlin/kotlin/collections/Arrays.kt +++ b/runtime/src/main/kotlin/kotlin/collections/Arrays.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. + * Copyright 2010-2018 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. @@ -16,28 +16,1340 @@ package kotlin.collections +import konan.internal.InlineConstructor +import kotlin.collections.* +import kotlin.internal.PureReifiable +import kotlin.util.sortArrayComparable +import kotlin.util.sortArrayWith +import kotlin.util.sortArray + +/** Returns the array if it's not `null`, or an empty array otherwise. */ +public actual inline fun Array?.orEmpty(): Array = this ?: emptyArray() + /** - * Returns a single list of all elements from all arrays in the given array. + * Returns new array which is a copy of the original array. */ -public fun Array>.flatten(): List { - val result = ArrayList(sumBy { it.size }) +@kotlin.internal.InlineOnly +public actual inline fun Array.copyOf(): Array { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun ByteArray.copyOf(): ByteArray { + return copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun ShortArray.copyOf(): ShortArray { + return copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun IntArray.copyOf(): IntArray { + return copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun LongArray.copyOf(): LongArray { + return copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun FloatArray.copyOf(): FloatArray { + return copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun DoubleArray.copyOf(): DoubleArray { + return copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun BooleanArray.copyOf(): BooleanArray { + return copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun CharArray.copyOf(): CharArray { + return copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + */ +@kotlin.internal.InlineOnly +public actual inline fun Array.copyOf(newSize: Int): Array { + return copyOfNulls(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + */ +@kotlin.internal.InlineOnly +public actual inline fun ByteArray.copyOf(newSize: Int): ByteArray { + return copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + */ +@kotlin.internal.InlineOnly +public actual inline fun ShortArray.copyOf(newSize: Int): ShortArray { + return copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + */ +@kotlin.internal.InlineOnly +public actual inline fun IntArray.copyOf(newSize: Int): IntArray { + return copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + */ +@kotlin.internal.InlineOnly +public actual inline fun LongArray.copyOf(newSize: Int): LongArray { + return copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + */ +@kotlin.internal.InlineOnly +public actual inline fun FloatArray.copyOf(newSize: Int): FloatArray { + return copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + */ +@kotlin.internal.InlineOnly +public actual inline fun DoubleArray.copyOf(newSize: Int): DoubleArray { + return copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + */ +@kotlin.internal.InlineOnly +public actual inline fun BooleanArray.copyOf(newSize: Int): BooleanArray { + return copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + */ +@kotlin.internal.InlineOnly +public actual inline fun CharArray.copyOf(newSize: Int): CharArray { + return copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of range of original array. + */ +// TODO: The method may check input or return Array. +// Now we check its input (fromIndex <= toIndex < size). +// Sync its behaviour wiht Kotlin JVM when the problem is solved there. +@kotlin.internal.InlineOnly +public actual inline fun Array.copyOfRange(fromIndex: Int, toIndex: Int): Array { + if (fromIndex > toIndex || toIndex > size) + throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns new array which is a copy of range of original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun ByteArray.copyOfRange(fromIndex: Int, toIndex: Int): ByteArray { + if (fromIndex > toIndex || toIndex > size) + throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns new array which is a copy of range of original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun ShortArray.copyOfRange(fromIndex: Int, toIndex: Int): ShortArray { + if (fromIndex > toIndex || toIndex > size) + throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns new array which is a copy of range of original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun IntArray.copyOfRange(fromIndex: Int, toIndex: Int): IntArray { + if (fromIndex > toIndex || toIndex > size) + throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns new array which is a copy of range of original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun LongArray.copyOfRange(fromIndex: Int, toIndex: Int): LongArray { + if (fromIndex > toIndex || toIndex > size) + throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns new array which is a copy of range of original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun FloatArray.copyOfRange(fromIndex: Int, toIndex: Int): FloatArray { + if (fromIndex > toIndex || toIndex > size) + throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns new array which is a copy of range of original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun DoubleArray.copyOfRange(fromIndex: Int, toIndex: Int): DoubleArray { + if (fromIndex > toIndex || toIndex > size) + throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns new array which is a copy of range of original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun BooleanArray.copyOfRange(fromIndex: Int, toIndex: Int): BooleanArray { + if (fromIndex > toIndex || toIndex > size) + throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns new array which is a copy of range of original array. + */ +@kotlin.internal.InlineOnly +public actual inline fun CharArray.copyOfRange(fromIndex: Int, toIndex: Int): CharArray { + if (fromIndex > toIndex || toIndex > size) + throw IllegalArgumentException("Wrong indices: fromIndex: $fromIndex, toIndex: $toIndex, array size: $size") + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Sorts the array in-place according to the order specified by the given [comparator]. + */ +public actual fun Array.sortWith(comparator: Comparator): Unit { + if (size > 1) sortArrayWith(this, 0, size, comparator) +} + +/** + * Sorts the array in-place according to the natural order of its elements. + * + * @throws ClassCastException if any element of the array is not [Comparable]. + */ +public actual fun > Array.sort(): Unit { + if (size > 1) sortArrayComparable(this) +} + +public fun Array.sortWith(comparator: Comparator, fromIndex: Int = 0, toIndex: Int = size): Unit { + sortArrayWith(this, fromIndex, toIndex, comparator) +} + +/** + * Sorts the array in-place. + */ +public actual fun IntArray.sort(): Unit { + if (size > 1) sortArray(this) +} + +/** + * Sorts the array in-place. + */ +public actual fun LongArray.sort(): Unit { + if (size > 1) sortArray(this) +} + +/** + * Sorts the array in-place. + */ +public actual fun ByteArray.sort(): Unit { + if (size > 1) sortArray(this) +} + +/** + * Sorts the array in-place. + */ +public actual fun ShortArray.sort(): Unit { + if (size > 1) sortArray(this) +} + +/** + * Sorts the array in-place. + */ +public actual fun DoubleArray.sort(): Unit { + if (size > 1) sortArray(this) +} + +/** + * Sorts the array in-place. + */ +public actual fun FloatArray.sort(): Unit { + if (size > 1) sortArray(this) +} + +/** + * Sorts the array in-place. + */ +public actual fun CharArray.sort(): Unit { + if (size > 1) sortArray(this) +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun ByteArray.toTypedArray(): Array { + val result = arrayOfNulls(size) + for (index in indices) + result[index] = this[index] + @Suppress("UNCHECKED_CAST") + return result as Array +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun ShortArray.toTypedArray(): Array { + val result = arrayOfNulls(size) + for (index in indices) + result[index] = this[index] + @Suppress("UNCHECKED_CAST") + return result as Array +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun IntArray.toTypedArray(): Array { + val result = arrayOfNulls(size) + for (index in indices) + result[index] = this[index] + @Suppress("UNCHECKED_CAST") + return result as Array +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun LongArray.toTypedArray(): Array { + val result = arrayOfNulls(size) + for (index in indices) + result[index] = this[index] + @Suppress("UNCHECKED_CAST") + return result as Array +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun FloatArray.toTypedArray(): Array { + val result = arrayOfNulls(size) + for (index in indices) + result[index] = this[index] + @Suppress("UNCHECKED_CAST") + return result as Array +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun DoubleArray.toTypedArray(): Array { + val result = arrayOfNulls(size) + for (index in indices) + result[index] = this[index] + @Suppress("UNCHECKED_CAST") + return result as Array +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun BooleanArray.toTypedArray(): Array { + val result = arrayOfNulls(size) + for (index in indices) + result[index] = this[index] + @Suppress("UNCHECKED_CAST") + return result as Array +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun CharArray.toTypedArray(): Array { + val result = arrayOfNulls(size) + for (index in indices) + result[index] = this[index] + @Suppress("UNCHECKED_CAST") + return result as Array +} + + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun Array.contentToString(): String { + return this.subarrayContentToString(offset = 0, length = this.size) +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun ByteArray.contentToString(): String { + if (size == 0) + return "[]" + val iMax = size - 1 + + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(this[i]) + if (i == iMax) + return b.append(']').toString() + b.append(", ") + i++ + } +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun ShortArray.contentToString(): String { + if (size == 0) + return "[]" + val iMax = size - 1 + + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(this[i]) + if (i == iMax) + return b.append(']').toString() + b.append(", ") + i++ + } +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun IntArray.contentToString(): String { + if (size == 0) + return "[]" + val iMax = size - 1 + + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(this[i]) + if (i == iMax) + return b.append(']').toString() + b.append(", ") + i++ + } +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun LongArray.contentToString(): String { + if (size == 0) + return "[]" + val iMax = size - 1 + + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(this[i]) + if (i == iMax) + return b.append(']').toString() + b.append(", ") + i++ + } +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun FloatArray.contentToString(): String { + if (size == 0) + return "[]" + val iMax = size - 1 + + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(this[i]) + if (i == iMax) + return b.append(']').toString() + b.append(", ") + i++ + } +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun DoubleArray.contentToString(): String { + if (size == 0) + return "[]" + val iMax = size - 1 + + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(this[i]) + if (i == iMax) + return b.append(']').toString() + b.append(", ") + i++ + } +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun BooleanArray.contentToString(): String { + if (size == 0) + return "[]" + val iMax = size - 1 + + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(this[i]) + if (i == iMax) + return b.append(']').toString() + b.append(", ") + i++ + } +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun CharArray.contentToString(): String { + if (size == 0) + return "[]" + val iMax = size - 1 + + val b = StringBuilder() + b.append('[') + var i = 0 + while (true) { + b.append(this[i]) + if (i == iMax) + return b.append(']').toString() + b.append(", ") + i++ + } +} + + +/** + * Returns a string representation of the contents of the subarray of the specified array as if it is [List]. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public inline fun Array.subarrayContentToString(offset: Int, length: Int): String { + val sb = StringBuilder(2 + length * 3) + sb.append("[") + var i = 0 + while (i < length) { + if (i > 0) sb.append(", ") + sb.append(this[offset + i]) + i++ + } + sb.append("]") + return sb.toString() +} + +/** + * Returns `true` if the two specified arrays are *deeply* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * If two corresponding elements are nested arrays, they are also compared deeply. + * If any of arrays contains itself on any nesting level the behavior is undefined. + */ +@SinceKotlin("1.1") +public actual infix fun Array.contentDeepEquals(other: Array): Boolean { + if (this === other) { + return true + } + + if (this.size != other.size) { + return false + } + + for (i in indices) { + val v1 = this[i] + val v2 = other[i] + + if (v1 == null || v2 == null) { + if (v1 == v2) { + continue + } else { + return false + } + } + + // TODO: Do a typecheck like if(v1.class == v2.class) return false + // Cases: + // Array + // Primitive array + // Some value (not an array) + + when { + v1 is Array<*> && v2 is Array<*> -> if (!v1.contentDeepEquals(v2)) return false + v1 is ByteArray && v2 is ByteArray -> if (!v1.contentEquals(v2)) return false + v1 is ShortArray && v2 is ShortArray -> if (!v1.contentEquals(v2)) return false + v1 is IntArray && v2 is IntArray -> if (!v1.contentEquals(v2)) return false + v1 is LongArray && v2 is LongArray -> if (!v1.contentEquals(v2)) return false + v1 is FloatArray && v2 is FloatArray -> if (!v1.contentEquals(v2)) return false + v1 is DoubleArray && v2 is DoubleArray -> if (!v1.contentEquals(v2)) return false + v1 is CharArray && v2 is CharArray -> if (!v1.contentEquals(v2)) return false + v1 is BooleanArray && v2 is BooleanArray -> if (!v1.contentEquals(v2)) return false + else -> if (v1 != v2) return false + } + + } + return true +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level the behavior is undefined. + */ +@SinceKotlin("1.1") +public actual fun Array.contentDeepHashCode(): Int { + var result = 1 for (element in this) { - result.addAll(element) + var elementHash = 0 + if (element is Array<*>) + elementHash = element.contentDeepHashCode() + else + element?.let { elementHash = element.hashCode() } + + result = 31 * result + elementHash } return result } /** - * Returns a pair of lists, where - * *first* list is built from the first values of each pair from this array, - * *second* list is built from the second values of each pair from this array. + * Returns a string representation of the contents of this array as if it is a [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level that reference + * is rendered as `"[...]"` to prevent recursion. */ -public fun Array>.unzip(): Pair, List> { - val listT = ArrayList(size) - val listR = ArrayList(size) - for (pair in this) { - listT.add(pair.first) - listR.add(pair.second) +@SinceKotlin("1.1") +public actual fun Array.contentDeepToString(): String { + val length = if (size * 5 + 2 > 0) size * 5 + 2 else Int.MAX_VALUE + val result = StringBuilder(length) + contentDeepToStringInternal(result, mutableSetOf()) + return result.toString() +} + +private fun Array.contentDeepToStringInternal(result: StringBuilder, processed: MutableSet>) { + if (this in processed) { + result.append("[...]") + return } - return listT to listR -} \ No newline at end of file + processed.add(this) + result.append('[') + + for (i in indices) { + if (i != 0) { + result.append(", ") + } + val element = this[i] + when (element) { + null -> result.append("null") + is Array<*> -> element.contentDeepToStringInternal(result, processed) + is ByteArray -> result.append(element.contentToString()) + is ShortArray -> result.append(element.contentToString()) + is IntArray -> result.append(element.contentToString()) + is LongArray -> result.append(element.contentToString()) + is FloatArray -> result.append(element.contentToString()) + is DoubleArray -> result.append(element.contentToString()) + is CharArray -> result.append(element.contentToString()) + is BooleanArray -> result.append(element.contentToString()) + else -> result.append(element.toString()) + } + } + + result.append(']') + processed.remove(this) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + */ +@SinceKotlin("1.1") +public actual infix fun Array.contentEquals(other: Array): Boolean { + if (this === other) { + return true + } + if (size != other.size) { + return false + } + for (i in indices) { + if (this[i] != other[i]) { + return false + } + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + */ +@SinceKotlin("1.1") +public actual infix fun ByteArray.contentEquals(other: ByteArray): Boolean { + if (this === other) { + return true + } + if (size != other.size) { + return false + } + for (i in indices) { + if (this[i] != other[i]) { + return false + } + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + */ +@SinceKotlin("1.1") +public actual infix fun ShortArray.contentEquals(other: ShortArray): Boolean { + if (this === other) { + return true + } + if (size != other.size) { + return false + } + for (i in indices) { + if (this[i] != other[i]) { + return false + } + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + */ +@SinceKotlin("1.1") +public actual infix fun IntArray.contentEquals(other: IntArray): Boolean { + if (this === other) { + return true + } + if (size != other.size) { + return false + } + for (i in indices) { + if (this[i] != other[i]) { + return false + } + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + */ +@SinceKotlin("1.1") +public actual infix fun LongArray.contentEquals(other: LongArray): Boolean { + if (this === other) { + return true + } + if (size != other.size) { + return false + } + for (i in indices) { + if (this[i] != other[i]) { + return false + } + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + */ +@SinceKotlin("1.1") +public actual infix fun FloatArray.contentEquals(other: FloatArray): Boolean { + if (this === other) { + return true + } + if (size != other.size) { + return false + } + for (i in indices) { + if (this[i] != other[i]) { + return false + } + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + */ +@SinceKotlin("1.1") +public actual infix fun DoubleArray.contentEquals(other: DoubleArray): Boolean { + if (this === other) { + return true + } + if (size != other.size) { + return false + } + for (i in indices) { + if (this[i] != other[i]) { + return false + } + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + */ +@SinceKotlin("1.1") +public actual infix fun BooleanArray.contentEquals(other: BooleanArray): Boolean { + if (this === other) { + return true + } + if (size != other.size) { + return false + } + for (i in indices) { + if (this[i] != other[i]) { + return false + } + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + */ +@SinceKotlin("1.1") +public actual infix fun CharArray.contentEquals(other: CharArray): Boolean { + if (this === other) { + return true + } + if (size != other.size) { + return false + } + for (i in indices) { + if (this[i] != other[i]) { + return false + } + } + return true +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun Array.contentHashCode(): Int { + var result = 1 + for (element in this) + result = 31 * result + (element?.hashCode() ?: 0) + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun ByteArray.contentHashCode(): Int { + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun ShortArray.contentHashCode(): Int { + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun IntArray.contentHashCode(): Int { + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun LongArray.contentHashCode(): Int { + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun FloatArray.contentHashCode(): Int { + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun DoubleArray.contentHashCode(): Int { + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun BooleanArray.contentHashCode(): Int { + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.1") +public actual fun CharArray.contentHashCode(): Int { + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +// From Library.kt. +/** + * Returns an array of objects of the given type with the given [size], initialized with null values. + */ +public inline fun arrayOfNulls(size: Int): Array = + @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") + arrayOfUninitializedElements(size) + +// From JS collections.kt. +internal actual fun arrayOfNulls(reference: Array, size: Int): Array { + return arrayOfNulls(size) as Array +} + +internal actual fun copyToArrayImpl(collection: Collection<*>): Array { + val array = arrayOfUninitializedElements(collection.size) + val iterator = collection.iterator() + var index = 0 + while (iterator.hasNext()) + array[index++] = iterator.next() + return array +} + +internal actual fun copyToArrayImpl(collection: Collection<*>, array: Array): Array { + if (array.size < collection.size) + return copyToArrayImpl(collection) as Array + + val iterator = collection.iterator() + var index = 0 + while (iterator.hasNext()) { + array[index++] = iterator.next() as T + } + if (index < array.size) { + return (array as Array).copyOf(index) as Array + } + return array +} + +/** + * Returns a *typed* array containing all of the elements of this collection. + * + * Allocates an array of runtime type `T` having its size equal to the size of this collection + * and populates the array with the elements of this collection. + */ +public actual inline fun Collection.toTypedArray(): Array { + val result = arrayOfNulls(size) + var index = 0 + for (element in this) result[index++] = element + @Suppress("UNCHECKED_CAST") + return result as Array +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun Array.plus(element: T): Array { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun ByteArray.plus(element: Byte): ByteArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun ShortArray.plus(element: Short): ShortArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun IntArray.plus(element: Int): IntArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun LongArray.plus(element: Long): LongArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun FloatArray.plus(element: Float): FloatArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun DoubleArray.plus(element: Double): DoubleArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun BooleanArray.plus(element: Boolean): BooleanArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun CharArray.plus(element: Char): CharArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun Array.plus(elements: Collection): Array { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun ByteArray.plus(elements: Collection): ByteArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun ShortArray.plus(elements: Collection): ShortArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun IntArray.plus(elements: Collection): IntArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun LongArray.plus(elements: Collection): LongArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun FloatArray.plus(elements: Collection): FloatArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun DoubleArray.plus(elements: Collection): DoubleArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun BooleanArray.plus(elements: Collection): BooleanArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun CharArray.plus(elements: Collection): CharArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun Array.plus(elements: Array): Array { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyRangeTo(result, 0, arraySize, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun ByteArray.plus(elements: ByteArray): ByteArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyRangeTo(result, 0, arraySize, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun ShortArray.plus(elements: ShortArray): ShortArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyRangeTo(result, 0, arraySize, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun IntArray.plus(elements: IntArray): IntArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyRangeTo(result, 0, arraySize, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun LongArray.plus(elements: LongArray): LongArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyRangeTo(result, 0, arraySize, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun FloatArray.plus(elements: FloatArray): FloatArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyRangeTo(result, 0, arraySize, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun DoubleArray.plus(elements: DoubleArray): DoubleArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyRangeTo(result, 0, arraySize, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun BooleanArray.plus(elements: BooleanArray): BooleanArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyRangeTo(result, 0, arraySize, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun CharArray.plus(elements: CharArray): CharArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyRangeTo(result, 0, arraySize, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +@kotlin.internal.InlineOnly +public actual inline fun Array.plusElement(element: T): Array { + return plus(element) +} diff --git a/runtime/src/main/kotlin/kotlin/collections/Collections.kt b/runtime/src/main/kotlin/kotlin/collections/Collections.kt index a4b560c92d9..efab69e7bb7 100644 --- a/runtime/src/main/kotlin/kotlin/collections/Collections.kt +++ b/runtime/src/main/kotlin/kotlin/collections/Collections.kt @@ -18,149 +18,16 @@ package kotlin.collections import kotlin.comparisons.* -internal object EmptyIterator : ListIterator { - override fun hasNext(): Boolean = false - override fun hasPrevious(): Boolean = false - override fun nextIndex(): Int = 0 - override fun previousIndex(): Int = -1 - override fun next(): Nothing = throw NoSuchElementException() - override fun previous(): Nothing = throw NoSuchElementException() -} - -internal object EmptyList : List, RandomAccess { - - override fun equals(other: Any?): Boolean = other is List<*> && other.isEmpty() - override fun hashCode(): Int = 1 - override fun toString(): String = "[]" - - override val size: Int get() = 0 - override fun isEmpty(): Boolean = true - override fun contains(element: Nothing): Boolean = false - override fun containsAll(elements: Collection): Boolean = elements.isEmpty() - - override fun get(index: Int): Nothing = throw IndexOutOfBoundsException("Empty list doesn't contain element at index $index.") - override fun indexOf(element: Nothing): Int = -1 - override fun lastIndexOf(element: Nothing): Int = -1 - - override fun iterator(): Iterator = EmptyIterator - override fun listIterator(): ListIterator = EmptyIterator - override fun listIterator(index: Int): ListIterator { - if (index != 0) throw IndexOutOfBoundsException("Index: $index") - return EmptyIterator - } - - override fun subList(fromIndex: Int, toIndex: Int): List { - if (fromIndex == 0 && toIndex == 0) return this - throw IndexOutOfBoundsException("fromIndex: $fromIndex, toIndex: $toIndex") - } - - private fun readResolve(): Any = EmptyList -} - -internal fun Array.asCollection(): Collection = ArrayAsCollection(this, isVarargs = false) - -private class ArrayAsCollection(val values: Array, val isVarargs: Boolean): Collection { - override val size: Int get() = values.size - override fun isEmpty(): Boolean = values.isEmpty() - override fun contains(element: T): Boolean = values.contains(element) - override fun containsAll(elements: Collection): Boolean = elements.all { contains(it) } - override fun iterator(): Iterator = values.iterator() - // override hidden toArray implementation to prevent copying of values array - public fun toArray(): Array = values.copyToArrayOfAny(isVarargs) -} - -/** Returns an empty read-only list. */ -public fun emptyList(): List = EmptyList - -/** Returns a new read-only list of given elements. */ -public fun listOf(vararg elements: T): List = if (elements.size > 0) elements.asList() else emptyList() - -/** Returns an empty read-only list. */ -@kotlin.internal.InlineOnly -public inline fun listOf(): List = emptyList() - -/** Returns a new [MutableList] with the given elements. */ -public fun mutableListOf(vararg elements: T): MutableList - = if (elements.size == 0) ArrayList() else ArrayList(ArrayAsCollection(elements, isVarargs = true)) - -// This part is from generated _Collections.kt. - -/** Returns a new [ArrayList] with the given elements. */ -public fun arrayListOf(vararg elements: T): ArrayList - = if (elements.size == 0) ArrayList() else ArrayList(ArrayAsCollection(elements, isVarargs = true)) - -/** Returns a new read-only list either of single given element, if it is not null, - * or empty list it the element is null.*/ -public fun listOfNotNull(element: T?): List = - if (element != null) listOf(element) else emptyList() - -/** Returns a new read-only list only of those given elements, that are not null. */ -public fun listOfNotNull(vararg elements: T?): List = elements.filterNotNull() - -/** - * Creates a new read-only list with the specified [size], where each element is calculated by calling the specified - * [init] function. The [init] function returns a list element given its index. - */ -@SinceKotlin("1.1") -@kotlin.internal.InlineOnly -public inline fun List(size: Int, init: (index: Int) -> T): List = MutableList(size, init) - -/** - * Creates a new mutable list with the specified [size], where each element is calculated by calling the specified - * [init] function. The [init] function returns a list element given its index. - */ -@SinceKotlin("1.1") -@kotlin.internal.InlineOnly -public inline fun MutableList(size: Int, init: (index: Int) -> T): MutableList { - val list = ArrayList(size) - repeat(size) { index -> list.add(init(index)) } - return list -} - -/** - * Returns an [IntRange] of the valid indices for this collection. - */ -public val Collection<*>.indices: IntRange - get() = 0..size - 1 - -/** - * Returns the index of the last item in the list or -1 if the list is empty. - * - * @sample samples.collections.Collections.Lists.lastIndexOfList - */ -public val List.lastIndex: Int - get() = this.size - 1 - -/** Returns `true` if the collection is not empty. */ -@kotlin.internal.InlineOnly -public inline fun Collection.isNotEmpty(): Boolean = !isEmpty() - -/** Returns this Collection if it's not `null` and the empty list otherwise. */ -@kotlin.internal.InlineOnly -public inline fun Collection?.orEmpty(): Collection = this ?: emptyList() - -@kotlin.internal.InlineOnly -public inline fun List?.orEmpty(): List = this ?: emptyList() - -/** - * Checks if all elements in the specified collection are contained in this collection. - * - * Allows to overcome type-safety restriction of `containsAll` that requires to pass a collection of type `Collection`. - */ -@kotlin.internal.InlineOnly -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -public inline fun <@kotlin.internal.OnlyInputTypes T> Collection.containsAll( - elements: Collection): Boolean = this.containsAll(elements) // copies typed varargs array to array of objects // TODO: generally wrong, wrt specialization. @FixmeSpecialization -private fun Array.copyToArrayOfAny(isVarargs: Boolean): Array = +internal actual fun Array.copyToArrayOfAny(isVarargs: Boolean): Array = if (isVarargs) // if the array came from varargs and already is array of Any, copying isn't required. - @Suppress("UNCHECKED_CAST") (this as Array) + @Suppress("UNCHECKED_CAST") (this as Array) else - @Suppress("UNCHECKED_CAST") (this.copyOfUninitializedElements(this.size) as Array) + @Suppress("UNCHECKED_CAST") (this.copyOfUninitializedElements(this.size) as Array) /** @@ -186,7 +53,7 @@ public interface MutableIterable : Iterable { override fun iterator(): MutableIterator } -public fun Array.asList(): List { +public actual fun Array.asList(): List { return object : AbstractList(), RandomAccess { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() @@ -200,7 +67,7 @@ public fun Array.asList(): List { /** * Returns a [List] that wraps the original array. */ -public fun ByteArray.asList(): List { +public actual fun ByteArray.asList(): List { return object : AbstractList(), RandomAccess { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() @@ -214,7 +81,7 @@ public fun ByteArray.asList(): List { /** * Returns a [List] that wraps the original array. */ -public fun ShortArray.asList(): List { +public actual fun ShortArray.asList(): List { return object : AbstractList(), RandomAccess { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() @@ -228,7 +95,7 @@ public fun ShortArray.asList(): List { /** * Returns a [List] that wraps the original array. */ -public fun IntArray.asList(): List { +public actual fun IntArray.asList(): List { return object : AbstractList(), RandomAccess { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() @@ -242,7 +109,7 @@ public fun IntArray.asList(): List { /** * Returns a [List] that wraps the original array. */ -public fun LongArray.asList(): List { +public actual fun LongArray.asList(): List { return object : AbstractList(), RandomAccess { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() @@ -256,7 +123,7 @@ public fun LongArray.asList(): List { /** * Returns a [List] that wraps the original array. */ -public fun FloatArray.asList(): List { +public actual fun FloatArray.asList(): List { return object : AbstractList(), RandomAccess { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() @@ -270,7 +137,7 @@ public fun FloatArray.asList(): List { /** * Returns a [List] that wraps the original array. */ -public fun DoubleArray.asList(): List { +public actual fun DoubleArray.asList(): List { return object : AbstractList(), RandomAccess { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() @@ -284,7 +151,7 @@ public fun DoubleArray.asList(): List { /** * Returns a [List] that wraps the original array. */ -public fun BooleanArray.asList(): List { +public actual fun BooleanArray.asList(): List { return object : AbstractList(), RandomAccess { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() @@ -298,7 +165,7 @@ public fun BooleanArray.asList(): List { /** * Returns a [List] that wraps the original array. */ -public fun CharArray.asList(): List { +public actual fun CharArray.asList(): List { return object : AbstractList(), RandomAccess { override val size: Int get() = this@asList.size override fun isEmpty(): Boolean = this@asList.isEmpty() @@ -309,928 +176,10 @@ public fun CharArray.asList(): List { } } -@Fixme -internal fun List.optimizeReadOnlyList() = this - -/** - * Searches this list or its range for the provided [element] using the binary search algorithm. - * The list is expected to be sorted into ascending order according to the Comparable natural ordering of its elements, - * otherwise the result is undefined. - * - * If the list contains multiple elements equal to the specified [element], there is no guarantee which one will be found. - * - * `null` value is considered to be less than any non-null value. - * - * @return the index of the element, if it is contained in the list within the specified range; - * otherwise, the inverted insertion point `(-insertion point - 1)`. - * The insertion point is defined as the index at which the element should be inserted, - * so that the list (or the specified subrange of list) still remains sorted. - */ -public fun > List.binarySearch(element: T?, fromIndex: Int = 0, toIndex: Int = size): Int { - rangeCheck(size, fromIndex, toIndex) - - var lowBorder = fromIndex - var highBorder = toIndex - 1 - - while (lowBorder <= highBorder) { - val middleIndex = (lowBorder + highBorder).ushr(1) // safe from overflows - val middleValue = get(middleIndex) - val comparisonResult = compareValues(middleValue, element) - - if (comparisonResult < 0) - lowBorder = middleIndex + 1 - else if (comparisonResult > 0) - highBorder = middleIndex - 1 - else - return middleIndex // key found - } - return -(lowBorder + 1) // key not found -} - -/** - * Searches this list or its range for the provided [element] using the binary search algorithm. - * The list is expected to be sorted into ascending order according to the specified [comparator], - * otherwise the result is undefined. - * - * If the list contains multiple elements equal to the specified [element], there is no guarantee which one will be found. - * - * `null` value is considered to be less than any non-null value. - * - * @return the index of the element, if it is contained in the list within the specified range; - * otherwise, the inverted insertion point `(-insertion point - 1)`. - * The insertion point is defined as the index at which the element should be inserted, - * so that the list (or the specified subrange of list) still remains sorted according to the specified [comparator]. - */ -public fun List.binarySearch(element: T, comparator: Comparator, fromIndex: Int = 0, toIndex: Int = size): Int { - rangeCheck(size, fromIndex, toIndex) - - var lowBorder = fromIndex - var highBorder = toIndex - 1 - - while (lowBorder <= highBorder) { - val middleIndex = (lowBorder + highBorder).ushr(1) // safe from overflows - val middleValue = get(middleIndex) - val comparisonResult = comparator.compare(middleValue, element) - - if (comparisonResult < 0) - lowBorder = middleIndex + 1 - else if (comparisonResult > 0) - highBorder = middleIndex - 1 - else - return middleIndex // key found - } - return -(lowBorder + 1) // key not found -} - -/** - * Searches this list or its range for an element having the key returned by the specified [selector] function - * equal to the provided [key] value using the binary search algorithm. - * The list is expected to be sorted into ascending order according to the Comparable natural ordering of keys of its elements. - * otherwise the result is undefined. - * - * If the list contains multiple elements with the specified [key], there is no guarantee which one will be found. - * - * `null` value is considered to be less than any non-null value. - * - * @return the index of the element with the specified [key], if it is contained in the list within the specified range; - * otherwise, the inverted insertion point `(-insertion point - 1)`. - * The insertion point is defined as the index at which the element should be inserted, - * so that the list (or the specified subrange of list) still remains sorted. - */ -public inline fun > List.binarySearchBy(key: K?, fromIndex: Int = 0, toIndex: Int = size, crossinline selector: (T) -> K?): Int = - binarySearch(fromIndex, toIndex) { compareValues(selector(it), key) } - -/** - * Searches this list or its range for an element for which [comparison] function returns zero using the binary search algorithm. - * The list is expected to be sorted into ascending order according to the provided [comparison], - * otherwise the result is undefined. - * - * If the list contains multiple elements for which [comparison] returns zero, there is no guarantee which one will be found. - * - * @param comparison function that compares an element of the list with the element being searched. - * - * @return the index of the found element, if it is contained in the list within the specified range; - * otherwise, the inverted insertion point `(-insertion point - 1)`. - * The insertion point is defined as the index at which the element should be inserted, - * so that the list (or the specified subrange of list) still remains sorted. - */ -public fun List.binarySearch(fromIndex: Int = 0, toIndex: Int = size, comparison: (T) -> Int): Int { - rangeCheck(size, fromIndex, toIndex) - - var lowBorder = fromIndex - var highBorder = toIndex - 1 - - while (lowBorder <= highBorder) { - val middleIndex = (lowBorder + highBorder).ushr(1) // safe from overflows - val middleValue = get(middleIndex) - val comparisonResult = comparison(middleValue) - - if (comparisonResult < 0) - lowBorder = middleIndex + 1 - else if (comparisonResult > 0) - highBorder = middleIndex - 1 - else - return middleIndex // key found - } - return -(lowBorder + 1) // key not found -} - -/** - * Checks that `from` and `to` are in - * the range of [0..size] and throws an appropriate exception, if they aren't. - */ -private fun rangeCheck(size: Int, fromIndex: Int, toIndex: Int) { - when { - fromIndex > toIndex -> throw IllegalArgumentException("fromIndex ($fromIndex) is greater than toIndex ($toIndex).") - fromIndex < 0 -> throw IndexOutOfBoundsException("fromIndex ($fromIndex) is less than zero.") - toIndex > size -> throw IndexOutOfBoundsException("toIndex ($toIndex) is greater than size ($size).") - } -} - - -// From generated _Collections.kt. -///////// - -/** - * Returns 1st *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun List.component1(): T { - return get(0) -} - -/** - * Returns 2nd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun List.component2(): T { - return get(1) -} - -/** - * Returns 3rd *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun List.component3(): T { - return get(2) -} - -/** - * Returns 4th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun List.component4(): T { - return get(3) -} - -/** - * Returns 5th *element* from the collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun List.component5(): T { - return get(4) -} - -/** - * Returns `true` if [element] is found in the collection. - */ -public operator fun <@kotlin.internal.OnlyInputTypes T> Iterable.contains(element: T): Boolean { - if (this is Collection) - return contains(element) - return indexOf(element) >= 0 -} - -/** - * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this collection. - */ -public fun Iterable.elementAt(index: Int): T { - if (this is List) - return get(index) - return elementAtOrElse(index) { throw IndexOutOfBoundsException("Collection doesn't contain element at index $index.") } -} - -/** - * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this list. - */ -@kotlin.internal.InlineOnly -public inline fun List.elementAt(index: Int): T { - return get(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this collection. - */ -public fun Iterable.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T { - if (this is List) - return this.getOrElse(index, defaultValue) - if (index < 0) - return defaultValue(index) - val iterator = iterator() - var count = 0 - while (iterator.hasNext()) { - val element = iterator.next() - if (index == count++) - return element - } - return defaultValue(index) -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this list. - */ -@kotlin.internal.InlineOnly -public inline fun List.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this collection. - */ -public fun Iterable.elementAtOrNull(index: Int): T? { - if (this is List) - return this.getOrNull(index) - if (index < 0) - return null - val iterator = iterator() - var count = 0 - while (iterator.hasNext()) { - val element = iterator.next() - if (index == count++) - return element - } - return null -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this list. - */ -@kotlin.internal.InlineOnly -public inline fun List.elementAtOrNull(index: Int): T? { - return this.getOrNull(index) -} - -/** - * Returns the first element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun Iterable.find(predicate: (T) -> Boolean): T? { - return firstOrNull(predicate) -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun Iterable.findLast(predicate: (T) -> Boolean): T? { - return lastOrNull(predicate) -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun List.findLast(predicate: (T) -> Boolean): T? { - return lastOrNull(predicate) -} - -/** - * Returns first element. - * @throws [NoSuchElementException] if the collection is empty. - */ -public fun Iterable.first(): T { - when (this) { - is List -> return this.first() - else -> { - val iterator = iterator() - if (!iterator.hasNext()) - throw NoSuchElementException("Collection is empty.") - return iterator.next() - } - } -} - -/** - * Returns first element. - * @throws [NoSuchElementException] if the list is empty. - */ -public fun List.first(): T { - if (isEmpty()) - throw NoSuchElementException("List is empty.") - return this[0] -} - -/** - * Returns the first element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun Iterable.first(predicate: (T) -> Boolean): T { - for (element in this) if (predicate(element)) return element - throw NoSuchElementException("Collection contains no element matching the predicate.") -} - -/** - * Returns the first element, or `null` if the collection is empty. - */ -public fun Iterable.firstOrNull(): T? { - when (this) { - is List -> { - if (isEmpty()) - return null - else - return this[0] - } - else -> { - val iterator = iterator() - if (!iterator.hasNext()) - return null - return iterator.next() - } - } -} - -/** - * Returns the first element, or `null` if the list is empty. - */ -public fun List.firstOrNull(): T? { - return if (isEmpty()) null else this[0] -} - -/** - * Returns the first element matching the given [predicate], or `null` if element was not found. - */ -public inline fun Iterable.firstOrNull(predicate: (T) -> Boolean): T? { - for (element in this) if (predicate(element)) return element - return null -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this list. - */ -@kotlin.internal.InlineOnly -public inline fun List.getOrElse(index: Int, defaultValue: (Int) -> T): T { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this list. - */ -public fun List.getOrNull(index: Int): T? { - return if (index >= 0 && index <= lastIndex) get(index) else null -} - -/** - * Returns first index of [element], or -1 if the collection does not contain element. - */ -public fun <@kotlin.internal.OnlyInputTypes T> Iterable.indexOf(element: T): Int { - if (this is List) return this.indexOf(element) - var index = 0 - for (item in this) { - if (element == item) - return index - index++ - } - return -1 -} - -/** - * Returns first index of [element], or -1 if the list does not contain element. - */ -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -public fun <@kotlin.internal.OnlyInputTypes T> List.indexOf(element: T): Int { - return indexOf(element) -} - -/** - * Returns index of the first element matching the given [predicate], or -1 if the collection does not contain such element. - */ -public inline fun Iterable.indexOfFirst(predicate: (T) -> Boolean): Int { - var index = 0 - for (item in this) { - if (predicate(item)) - return index - index++ - } - return -1 -} - -/** - * Returns index of the first element matching the given [predicate], or -1 if the list does not contain such element. - */ -public inline fun List.indexOfFirst(predicate: (T) -> Boolean): Int { - var index = 0 - for (item in this) { - if (predicate(item)) - return index - index++ - } - return -1 -} - -/** - * Returns index of the last element matching the given [predicate], or -1 if the collection does not contain such element. - */ -public inline fun Iterable.indexOfLast(predicate: (T) -> Boolean): Int { - var lastIndex = -1 - var index = 0 - for (item in this) { - if (predicate(item)) - lastIndex = index - index++ - } - return lastIndex -} - -/** - * Returns index of the last element matching the given [predicate], or -1 if the list does not contain such element. - */ -public inline fun List.indexOfLast(predicate: (T) -> Boolean): Int { - val iterator = this.listIterator(size) - while (iterator.hasPrevious()) { - if (predicate(iterator.previous())) { - return iterator.nextIndex() - } - } - return -1 -} - -/** - * Returns the last element. - * @throws [NoSuchElementException] if the collection is empty. - */ -public fun Iterable.last(): T { - when (this) { - is List -> return this.last() - else -> { - val iterator = iterator() - if (!iterator.hasNext()) - throw NoSuchElementException("Collection is empty.") - var last = iterator.next() - while (iterator.hasNext()) - last = iterator.next() - return last - } - } -} - -/** - * Returns the last element. - * @throws [NoSuchElementException] if the list is empty. - */ -public fun List.last(): T { - if (isEmpty()) - throw NoSuchElementException("List is empty.") - return this[lastIndex] -} - -/** - * Returns the last element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun Iterable.last(predicate: (T) -> Boolean): T { - var last: T? = null - var found = false - for (element in this) { - if (predicate(element)) { - last = element - found = true - } - } - if (!found) throw NoSuchElementException("Collection contains no element matching the predicate.") - @Suppress("UNCHECKED_CAST") - return last as T -} - -/** - * Returns the last element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun List.last(predicate: (T) -> Boolean): T { - val iterator = this.listIterator(size) - while (iterator.hasPrevious()) { - val element = iterator.previous() - if (predicate(element)) return element - } - throw NoSuchElementException("List contains no element matching the predicate.") -} - -/** - * Returns last index of [element], or -1 if the collection does not contain element. - */ -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -public fun <@kotlin.internal.OnlyInputTypes T> Iterable.lastIndexOf(element: T): Int { - if (this is List) return this.lastIndexOf(element) - var lastIndex = -1 - var index = 0 - for (item in this) { - if (element == item) - lastIndex = index - index++ - } - return lastIndex -} - -/** - * Returns last index of [element], or -1 if the list does not contain element. - */ -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -public fun <@kotlin.internal.OnlyInputTypes T> List.lastIndexOf(element: T): Int { - return lastIndexOf(element) -} - -/** - * Returns the last element, or `null` if the collection is empty. - */ -public fun Iterable.lastOrNull(): T? { - when (this) { - is List -> return if (isEmpty()) null else this[size - 1] - else -> { - val iterator = iterator() - if (!iterator.hasNext()) - return null - var last = iterator.next() - while (iterator.hasNext()) - last = iterator.next() - return last - } - } -} - -/** - * Returns the last element, or `null` if the list is empty. - */ -public fun List.lastOrNull(): T? { - return if (isEmpty()) null else this[size - 1] -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun Iterable.lastOrNull(predicate: (T) -> Boolean): T? { - var last: T? = null - for (element in this) { - if (predicate(element)) { - last = element - } - } - return last -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun List.lastOrNull(predicate: (T) -> Boolean): T? { - val iterator = this.listIterator(size) - while (iterator.hasPrevious()) { - val element = iterator.previous() - if (predicate(element)) return element - } - return null -} - -/** - * Returns the single element, or throws an exception if the collection is empty or has more than one element. - */ -public fun Iterable.single(): T { - when (this) { - is List -> return this.single() - else -> { - val iterator = iterator() - if (!iterator.hasNext()) - throw NoSuchElementException("Collection is empty.") - val single = iterator.next() - if (iterator.hasNext()) - throw IllegalArgumentException("Collection has more than one element.") - return single - } - } -} - -/** - * Returns the single element, or throws an exception if the list is empty or has more than one element. - */ -public fun List.single(): T { - return when (size) { - 0 -> throw NoSuchElementException("List is empty.") - 1 -> this[0] - else -> throw IllegalArgumentException("List has more than one element.") - } -} - -/** - * Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. - */ -public inline fun Iterable.single(predicate: (T) -> Boolean): T { - var single: T? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) throw IllegalArgumentException("Collection contains more than one matching element.") - single = element - found = true - } - } - if (!found) throw NoSuchElementException("Collection contains no element matching the predicate.") - @Suppress("UNCHECKED_CAST") - return single as T -} - -/** - * Returns single element, or `null` if the collection is empty or has more than one element. - */ -public fun Iterable.singleOrNull(): T? { - when (this) { - is List -> return if (size == 1) this[0] else null - else -> { - val iterator = iterator() - if (!iterator.hasNext()) - return null - val single = iterator.next() - if (iterator.hasNext()) - return null - return single - } - } -} - -/** - * Returns single element, or `null` if the list is empty or has more than one element. - */ -public fun List.singleOrNull(): T? { - return if (size == 1) this[0] else null -} - -/** - * Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. - */ -public inline fun Iterable.singleOrNull(predicate: (T) -> Boolean): T? { - var single: T? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) return null - single = element - found = true - } - } - if (!found) return null - return single -} - -/** - * Returns a list containing all elements except first [n] elements. - */ -public fun Iterable.drop(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return toList() - val list: ArrayList - if (this is Collection<*>) { - val resultSize = size - n - if (resultSize <= 0) - return emptyList() - if (resultSize == 1) - return listOf(last()) - list = ArrayList(resultSize) - if (this is List) { - if (this is RandomAccess) { - for (index in n..size - 1) - list.add(this[index]) - } else { - for (item in this.listIterator(n)) - list.add(item) - } - return list - } - } - else { - list = ArrayList() - } - var count = 0 - for (item in this) { - if (count++ >= n) list.add(item) - } - return list.optimizeReadOnlyList() -} - -/** - * Returns a list containing all elements except last [n] elements. - */ -public fun List.dropLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - return take((size - n).coerceAtLeast(0)) -} - -/** - * Returns a list containing all elements except last elements that satisfy the given [predicate]. - */ -public inline fun List.dropLastWhile(predicate: (T) -> Boolean): List { - if (!isEmpty()) { - val iterator = this.listIterator(size) - while (iterator.hasPrevious()) { - if (!predicate(iterator.previous())) { - return take(iterator.nextIndex() + 1) - } - } - } - return emptyList() -} - -/** - * Returns a list containing all elements except first elements that satisfy the given [predicate]. - */ -public inline fun Iterable.dropWhile(predicate: (T) -> Boolean): List { - var yielding = false - val list = ArrayList() - for (item in this) - if (yielding) - list.add(item) - else if (!predicate(item)) { - list.add(item) - yielding = true - } - return list -} - -/** - * Returns a list containing only elements matching the given [predicate]. - */ -public inline fun Iterable.filter(predicate: (T) -> Boolean): List { - return filterTo(ArrayList(), predicate) -} - -/** - * Returns a list containing only elements matching the given [predicate]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun Iterable.filterIndexed(predicate: (Int, T) -> Boolean): List { - return filterIndexedTo(ArrayList(), predicate) -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun > Iterable.filterIndexedTo(destination: C, predicate: (Int, T) -> Boolean): C { - forEachIndexed { index, element -> - if (predicate(index, element)) destination.add(element) - } - return destination -} - -/** - * Returns a list containing all elements that are instances of specified type parameter R. - */ -public inline fun Iterable<*>.filterIsInstance(): List<@kotlin.internal.NoInfer R> { - return filterIsInstanceTo(ArrayList()) -} - -/** - * Appends all elements that are instances of specified type parameter R to the given [destination]. - */ -public inline fun > Iterable<*>.filterIsInstanceTo(destination: C): C { - for (element in this) if (element is R) destination.add(element) - return destination -} - - -/** - * Returns a list containing all elements not matching the given [predicate]. - */ -public inline fun Iterable.filterNot(predicate: (T) -> Boolean): List { - return filterNotTo(ArrayList(), predicate) -} - -/** - * Returns a list containing all elements that are not `null`. - */ -public fun Iterable.filterNotNull(): List { - return filterNotNullTo(ArrayList()) -} - -/** - * Appends all elements that are not `null` to the given [destination]. - */ -public fun , T : Any> Iterable.filterNotNullTo(destination: C): C { - for (element in this) if (element != null) destination.add(element) - return destination -} - -/** - * Appends all elements not matching the given [predicate] to the given [destination]. - */ -public inline fun > Iterable.filterNotTo(destination: C, predicate: (T) -> Boolean): C { - for (element in this) if (!predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - */ -public inline fun > Iterable.filterTo(destination: C, predicate: (T) -> Boolean): C { - for (element in this) if (predicate(element)) destination.add(element) - return destination -} - -/** - * Returns a list containing elements at indices in the specified [indices] range. - */ -public fun List.slice(indices: IntRange): List { - if (indices.isEmpty()) return listOf() - return this.subList(indices.start, indices.endInclusive + 1).toList() -} - -/** - * Returns a list containing elements at specified [indices]. - */ -public fun List.slice(indices: Iterable): List { - val size = indices.collectionSizeOrDefault(10) - if (size == 0) return emptyList() - val list = ArrayList(size) - for (index in indices) { - list.add(get(index)) - } - return list -} - -/** - * Returns a list containing first [n] elements. - */ -public fun Iterable.take(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - if (this is Collection) { - if (n >= size) return toList() - if (n == 1) return listOf(first()) - } - var count = 0 - val list = ArrayList(n) - for (item in this) { - if (count++ == n) - break - list.add(item) - } - return list.optimizeReadOnlyList() -} - -/** - * Returns a list containing last [n] elements. - */ -public fun List.takeLast(n: Int): List { - require(n >= 0) { "Requested element count $n is less than zero." } - if (n == 0) return emptyList() - val size = size - if (n >= size) return toList() - if (n == 1) return listOf(last()) - val list = ArrayList(n) - if (this is RandomAccess) { - for (index in size - n .. size - 1) - list.add(this[index]) - } else { - for (item in this.listIterator(size - n)) - list.add(item) - } - return list -} - -/** - * Returns a list containing last elements satisfying the given [predicate]. - */ -public inline fun List.takeLastWhile(predicate: (T) -> Boolean): List { - if (isEmpty()) - return emptyList() - val iterator = this.listIterator(size) - while (iterator.hasPrevious()) { - if (!predicate(iterator.previous())) { - iterator.next() - val expectedSize = size - iterator.nextIndex() - if (expectedSize == 0) return emptyList() - return ArrayList(expectedSize).apply { - while (iterator.hasNext()) - add(iterator.next()) - } - } - } - return toList() -} - -/** - * Returns a list containing first elements satisfying the given [predicate]. - */ -public inline fun Iterable.takeWhile(predicate: (T) -> Boolean): List { - val list = ArrayList() - for (item in this) { - if (!predicate(item)) - break - list.add(item) - } - return list -} - /** * Reverses elements in the list in-place. */ -public fun MutableList.reverse(): Unit { +public actual fun MutableList.reverse(): Unit { val median = size / 2 var leftIndex = 0 var rightIndex = size - 1 @@ -1241,38 +190,6 @@ public fun MutableList.reverse(): Unit { leftIndex++ rightIndex-- } - -} - -/** - * Returns a list with elements in reversed order. - */ -public fun Iterable.reversed(): List { - if (this is Collection && size <= 1) return toList() - val list = toMutableList() - list.reverse() - return list -} - -/** - * Sorts elements in the list in-place according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > MutableList.sortBy(crossinline selector: (T) -> R?): Unit { - if (size > 1) sortWith(compareBy(selector)) -} - -/** - * Sorts elements in the list in-place descending according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > MutableList.sortByDescending(crossinline selector: (T) -> R?): Unit { - if (size > 1) sortWith(compareByDescending(selector)) -} - -/** - * Sorts elements in the list in-place descending according to their natural sort order. - */ -public fun > MutableList.sortDescending(): Unit { - sortWith(reverseOrder()) } /** @@ -1287,1528 +204,49 @@ public fun MutableList.replaceAll(transformation: (T) -> T) { } /** - * Returns a list of all elements sorted according to their natural sort order. - */ -public fun > Iterable.sorted(): List { - if (this is Collection) { - if (size <= 1) return this.toList() - @Suppress("UNCHECKED_CAST") - return (toTypedArray>() as Array).apply { sort() }.asList() - } - return toMutableList().apply { sort() } -} - -/** - * Returns a list of all elements sorted according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > Iterable.sortedBy(crossinline selector: (T) -> R?): List { - return sortedWith(compareBy(selector)) -} - -/** - * Returns a list of all elements sorted descending according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > Iterable.sortedByDescending(crossinline selector: (T) -> R?): List { - return sortedWith(compareByDescending(selector)) -} - -/** - * Returns a list of all elements sorted descending according to their natural sort order. - */ -public fun > Iterable.sortedDescending(): List { - return sortedWith(reverseOrder()) -} - -/** - * Returns a list of all elements sorted according to the specified [comparator]. - */ -public fun Iterable.sortedWith(comparator: Comparator): List { - if (this is Collection) { - if (size <= 1) return this.toList() - @Suppress("UNCHECKED_CAST") - return (toTypedArray() as Array).apply { sortWith(comparator) }.asList() - } - return toMutableList().apply { sortWith(comparator) } -} - -/** - * Returns an array of Boolean containing all of the elements of this collection. - */ -public fun Collection.toBooleanArray(): BooleanArray { - val result = BooleanArray(size) - var index = 0 - for (element in this) - result[index++] = element - return result -} - -/** - * Returns an array of Byte containing all of the elements of this collection. - */ -public fun Collection.toByteArray(): ByteArray { - val result = ByteArray(size) - var index = 0 - for (element in this) - result[index++] = element - return result -} - -/** - * Returns an array of Char containing all of the elements of this collection. - */ -public fun Collection.toCharArray(): CharArray { - val result = CharArray(size) - var index = 0 - for (element in this) - result[index++] = element - return result -} - -/** - * Returns an array of Double containing all of the elements of this collection. - */ -public fun Collection.toDoubleArray(): DoubleArray { - val result = DoubleArray(size) - var index = 0 - for (element in this) - result[index++] = element - return result -} - -/** - * Returns an array of Float containing all of the elements of this collection. - */ -public fun Collection.toFloatArray(): FloatArray { - val result = FloatArray(size) - var index = 0 - for (element in this) - result[index++] = element - return result -} - -/** - * Returns an array of Int containing all of the elements of this collection. - */ -public fun Collection.toIntArray(): IntArray { - val result = IntArray(size) - var index = 0 - for (element in this) - result[index++] = element - return result -} - -/** - * Returns an array of Long containing all of the elements of this collection. - */ -public fun Collection.toLongArray(): LongArray { - val result = LongArray(size) - var index = 0 - for (element in this) - result[index++] = element - return result -} - -/** - * Returns an array of Short containing all of the elements of this collection. - */ -public fun Collection.toShortArray(): ShortArray { - val result = ShortArray(size) - var index = 0 - for (element in this) - result[index++] = element - return result -} - -/** - * Returns a [Map] containing key-value pairs provided by [transform] function - * applied to elements of the given collection. + * Groups elements from the [Grouping] source by key and counts elements in each group. * - * If any of two pairs would have the same key the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original collection. - */ -public inline fun Iterable.associate(transform: (T) -> Pair): Map { - val capacity = mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16) - return associateTo(LinkedHashMap(capacity), transform) -} - -/** - * Returns a [Map] containing the elements from the given collection indexed by the key - * returned from [keySelector] function applied to each element. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original collection. - */ -public inline fun Iterable.associateBy(keySelector: (T) -> K): Map { - val capacity = mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector) -} - -/** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given collection. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original collection. - */ -public inline fun Iterable.associateBy(keySelector: (T) -> K, valueTransform: (T) -> V): Map { - val capacity = mapCapacity(collectionSizeOrDefault(10)).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function applied to each element of the given collection - * and value is the element itself. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > Iterable.associateByTo(destination: M, keySelector: (T) -> K): M { - for (element in this) { - destination.put(keySelector(element), element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and - * and value is provided by the [valueTransform] function applied to elements of the given collection. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > Iterable.associateByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V): M { - for (element in this) { - destination.put(keySelector(element), valueTransform(element)) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs - * provided by [transform] function applied to each element of the given collection. - * - * If any of two pairs would have the same key the last one gets added to the map. - */ -public inline fun > Iterable.associateTo(destination: M, transform: (T) -> Pair): M { - for (element in this) { - destination += transform(element) - } - return destination -} - -/** - * Appends all elements to the given [destination] collection. - */ -public fun > Iterable.toCollection(destination: C): C { - for (item in this) { - destination.add(item) - } - return destination -} - -/** - * Returns a [HashSet] of all elements. - */ -public fun Iterable.toHashSet(): HashSet { - return toCollection(HashSet(mapCapacity(collectionSizeOrDefault(12)))) -} - -/** - * Returns a [List] containing all elements. - */ -public fun Iterable.toList(): List { - if (this is Collection) { - return when (size) { - 0 -> emptyList() - 1 -> listOf(if (this is List) get(0) else iterator().next()) - else -> this.toMutableList() - } - } - return this.toMutableList().optimizeReadOnlyList() -} - -/** - * Returns a [MutableList] filled with all elements of this collection. - */ -public fun Iterable.toMutableList(): MutableList { - if (this is Collection) - return this.toMutableList() - return toCollection(ArrayList()) -} - -/** - * Returns a [MutableList] filled with all elements of this collection. - */ -public fun Collection.toMutableList(): MutableList { - return ArrayList(this) -} - -/** - * Returns a [Set] of all elements. - * - * The returned set preserves the element iteration order of the original collection. - */ -public fun Iterable.toSet(): Set { - if (this is Collection) { - return when (size) { - 0 -> emptySet() - 1 -> setOf(if (this is List) this[0] else iterator().next()) - else -> toCollection(LinkedHashSet(mapCapacity(size))) - } - } - return toCollection(LinkedHashSet()).optimizeReadOnlySet() -} - -/** - * Returns a [SortedSet] of all elements. - */ -//public fun > Iterable.toSortedSet(): SortedSet { -// return toCollection(TreeSet()) -//} - -/** - * Returns a [SortedSet] of all elements. - * - * Elements in the set returned are sorted according to the given [comparator]. - */ -//public fun Iterable.toSortedSet(comparator: Comparator): SortedSet { -// return toCollection(TreeSet(comparator)) -//} - -/** - * Returns a single list of all elements yielded from results of [transform] function being invoked on each element of original collection. - */ -public inline fun Iterable.flatMap(transform: (T) -> Iterable): List { - return flatMapTo(ArrayList(), transform) -} - -/** - * Appends all elements yielded from results of [transform] function being invoked on each element of original collection, to the given [destination]. - */ -public inline fun > Iterable.flatMapTo(destination: C, transform: (T) -> Iterable): C { - for (element in this) { - val list = transform(element) - destination.addAll(list) - } - return destination -} - -/** - * Groups elements of the original collection by the key returned by the given [keySelector] function - * applied to each element and returns a map where each group key is associated with a list of corresponding elements. - * - * The returned map preserves the entry iteration order of the keys produced from the original collection. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun Iterable.groupBy(keySelector: (T) -> K): Map> { - return groupByTo(LinkedHashMap>(), keySelector) -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original collection - * by the key returned by the given [keySelector] function applied to the element - * and returns a map where each group key is associated with a list of corresponding values. - * - * The returned map preserves the entry iteration order of the keys produced from the original collection. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun Iterable.groupBy(keySelector: (T) -> K, valueTransform: (T) -> V): Map> { - return groupByTo(LinkedHashMap>(), keySelector, valueTransform) -} - -/** - * Groups elements of the original collection by the key returned by the given [keySelector] function - * applied to each element and puts to the [destination] map each group key associated with a list of corresponding elements. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun >> Iterable.groupByTo(destination: M, keySelector: (T) -> K): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(element) - } - return destination -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original collection - * by the key returned by the given [keySelector] function applied to the element - * and puts to the [destination] map each group key associated with a list of corresponding values. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun >> Iterable.groupByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(valueTransform(element)) - } - return destination -} - -/** - * Creates a [Grouping] source from a collection to be used later with one of group-and-fold operations - * using the specified [keySelector] function to extract a key from each element. + * @return a [Map] associating the key of each group with the count of elements in the group. * * @sample samples.collections.Collections.Transformations.groupingByEachCount */ @SinceKotlin("1.1") -public inline fun Iterable.groupingBy(crossinline keySelector: (T) -> K): Grouping { - return object : Grouping { - override fun sourceIterator(): Iterator = this@groupingBy.iterator() - override fun keyOf(element: T): K = keySelector(element) - } -} +public actual fun Grouping.eachCount(): Map = eachCountTo(mutableMapOf()) + +// Copied from JS. /** - * Returns a list containing the results of applying the given [transform] function - * to each element in the original collection. - */ -public inline fun Iterable.map(transform: (T) -> R): List { - @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") - return mapTo(ArrayList(collectionSizeOrDefault(10)), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each element and its index in the original collection. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun Iterable.mapIndexed(transform: (Int, T) -> R): List { - @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") - return mapIndexedTo(ArrayList(collectionSizeOrDefault(10)), transform) -} - -/** - * Returns a list containing only the non-null results of applying the given [transform] function - * to each element and its index in the original collection. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun Iterable.mapIndexedNotNull(transform: (Int, T) -> R?): List { - return mapIndexedNotNullTo(ArrayList(), transform) -} - -/** - * Applies the given [transform] function to each element and its index in the original collection - * and appends only the non-null results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > Iterable.mapIndexedNotNullTo(destination: C, transform: (Int, T) -> R?): C { - forEachIndexed { index, element -> transform(index, element)?.let { destination.add(it) } } - return destination -} - -/** - * Applies the given [transform] function to each element and its index in the original collection - * and appends the results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > Iterable.mapIndexedTo(destination: C, transform: (Int, T) -> R): C { - var index = 0 - for (item in this) - destination.add(transform(index++, item)) - return destination -} - -/** - * Returns a list containing only the non-null results of applying the given [transform] function - * to each element in the original collection. - */ -public inline fun Iterable.mapNotNull(transform: (T) -> R?): List { - return mapNotNullTo(ArrayList(), transform) -} - -/** - * Applies the given [transform] function to each element in the original collection - * and appends only the non-null results to the given [destination]. - */ -public inline fun > Iterable.mapNotNullTo(destination: C, transform: (T) -> R?): C { - forEach { element -> transform(element)?.let { destination.add(it) } } - return destination -} - -/** - * Applies the given [transform] function to each element of the original collection - * and appends the results to the given [destination]. - */ -public inline fun > Iterable.mapTo(destination: C, transform: (T) -> R): C { - for (item in this) - destination.add(transform(item)) - return destination -} - -/** - * Returns a lazy [Iterable] of [IndexedValue] for each element of the original collection. - */ -public fun Iterable.withIndex(): Iterable> { - return IndexingIterable { iterator() } -} - -/** - * Returns a list containing only distinct elements from the given collection. + * Fills the list with the provided [value]. * - * The elements in the resulting list are in the same order as they were in the source collection. - */ -public fun Iterable.distinct(): List { - return this.toMutableSet().toList() -} - -/** - * Returns a list containing only elements from the given collection - * having distinct keys returned by the given [selector] function. - * - * The elements in the resulting list are in the same order as they were in the source collection. - */ -public inline fun Iterable.distinctBy(selector: (T) -> K): List { - val set = HashSet() - val list = ArrayList() - for (e in this) { - val key = selector(e) - if (set.add(key)) - list.add(e) - } - return list -} - -/** - * Returns a set containing all elements that are contained by both this set and the specified collection. - * - * The returned set preserves the element iteration order of the original collection. - */ -public infix fun Iterable.intersect(other: Iterable): Set { - val set = this.toMutableSet() - set.retainAll(other) - return set -} - -/** - * Returns a set containing all elements that are contained by this collection and not contained by the specified collection. - * - * The returned set preserves the element iteration order of the original collection. - */ -public infix fun Iterable.subtract(other: Iterable): Set { - val set = this.toMutableSet() - set.removeAll(other) - return set -} - -/** - * Returns a mutable set containing all distinct elements from the given collection. - * - * The returned set preserves the element iteration order of the original collection. - */ -public fun Iterable.toMutableSet(): MutableSet { - return when (this) { - is Collection -> LinkedHashSet(this) - else -> toCollection(LinkedHashSet()) - } -} - -/** - * Returns a set containing all distinct elements from both collections. - * - * The returned set preserves the element iteration order of the original collection. - * Those elements of the [other] collection that are unique are iterated in the end - * in the order of the [other] collection. - */ -public infix fun Iterable.union(other: Iterable): Set { - val set = this.toMutableSet() - set.addAll(other) - return set -} - -/** - * Returns `true` if all elements match the given [predicate]. - */ -public inline fun Iterable.all(predicate: (T) -> Boolean): Boolean { - for (element in this) if (!predicate(element)) return false - return true -} - -/** - * Returns `true` if collection has at least one element. - */ -public fun Iterable.any(): Boolean { - for (element in this) return true - return false -} - -/** - * Returns `true` if at least one element matches the given [predicate]. - */ -public inline fun Iterable.any(predicate: (T) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return true - return false -} - -/** - * Returns the number of elements in this collection. - * Returns the number of elements in this collection. - */ -public fun Iterable.count(): Int { - var count = 0 - for (element in this) count++ - return count -} - -/** - * Returns the number of elements in this collection. - */ -@kotlin.internal.InlineOnly -public inline fun Collection.count(): Int { - return size -} - -/** - * Returns the number of elements matching the given [predicate]. - */ -public inline fun Iterable.count(predicate: (T) -> Boolean): Int { - var count = 0 - for (element in this) if (predicate(element)) count++ - return count -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun Iterable.fold(initial: R, operation: (R, T) -> R): R { - var accumulator = initial - for (element in this) accumulator = operation(accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right - * to current accumulator value and each element with its index in the original collection. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself, and calculates the next accumulator value. - */ -public inline fun Iterable.foldIndexed(initial: R, operation: (Int, R, T) -> R): R { - var index = 0 - var accumulator = initial - for (element in this) accumulator = operation(index++, accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun List.foldRight(initial: R, operation: (T, R) -> R): R { - var accumulator = initial - if (!isEmpty()) { - val iterator = this.listIterator(size) - while (iterator.hasPrevious()) { - accumulator = operation(iterator.previous(), accumulator) - } - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left - * to each element with its index in the original list and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun List.foldRightIndexed(initial: R, operation: (Int, T, R) -> R): R { - var accumulator = initial - if (!isEmpty()) { - val iterator = this.listIterator(size) - while (iterator.hasPrevious()) { - val index = iterator.previousIndex() - accumulator = operation(index, iterator.previous(), accumulator) - } - } - return accumulator -} - -/** - * Performs the given [action] on each element. - */ -@kotlin.internal.HidesMembers -public inline fun Iterable.forEach(action: (T) -> Unit): Unit { - for (element in this) action(element) -} - -/** - * Performs the given [action] on each element, providing sequential index with the element. - * @param [action] function that takes the index of an element and the element itself - * and performs the desired action on the element. - */ -public inline fun Iterable.forEachIndexed(action: (Int, T) -> Unit): Unit { - var index = 0 - for (item in this) action(index++, item) -} - -/** - * Returns the largest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -@SinceKotlin("1.1") -public fun Iterable.max(): Double? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var max = iterator.next() - if (max.isNaN()) return max - while (iterator.hasNext()) { - val e = iterator.next() - if (e.isNaN()) return e - if (max < e) max = e - } - return max -} - -/** - * Returns the largest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -@SinceKotlin("1.1") -public fun Iterable.max(): Float? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var max = iterator.next() - if (max.isNaN()) return max - while (iterator.hasNext()) { - val e = iterator.next() - if (e.isNaN()) return e - if (max < e) max = e - } - return max -} - -/** - * Returns the largest element or `null` if there are no elements. - */ -public fun > Iterable.max(): T? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var max = iterator.next() - while (iterator.hasNext()) { - val e = iterator.next() - if (max < e) max = e - } - return max -} - -/** - * Returns the first element yielding the largest value of the given function or `null` if there are no elements. - */ -public inline fun > Iterable.maxBy(selector: (T) -> R): T? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var maxElem = iterator.next() - var maxValue = selector(maxElem) - while (iterator.hasNext()) { - val e = iterator.next() - val v = selector(e) - if (maxValue < v) { - maxElem = e - maxValue = v - } - } - return maxElem -} - -/** - * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun Iterable.maxWith(comparator: Comparator): T? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var max = iterator.next() - while (iterator.hasNext()) { - val e = iterator.next() - if (comparator.compare(max, e) < 0) max = e - } - return max -} - -/** - * Returns the smallest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -@SinceKotlin("1.1") -public fun Iterable.min(): Double? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var min = iterator.next() - if (min.isNaN()) return min - while (iterator.hasNext()) { - val e = iterator.next() - if (e.isNaN()) return e - if (min > e) min = e - } - return min -} - -/** - * Returns the smallest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -@SinceKotlin("1.1") -public fun Iterable.min(): Float? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var min = iterator.next() - if (min.isNaN()) return min - while (iterator.hasNext()) { - val e = iterator.next() - if (e.isNaN()) return e - if (min > e) min = e - } - return min -} - -/** - * Returns the smallest element or `null` if there are no elements. - */ -public fun > Iterable.min(): T? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var min = iterator.next() - while (iterator.hasNext()) { - val e = iterator.next() - if (min > e) min = e - } - return min -} - -/** - * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. - */ -public inline fun > Iterable.minBy(selector: (T) -> R): T? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var minElem = iterator.next() - var minValue = selector(minElem) - while (iterator.hasNext()) { - val e = iterator.next() - val v = selector(e) - if (minValue > v) { - minElem = e - minValue = v - } - } - return minElem -} - -/** - * Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun Iterable.minWith(comparator: Comparator): T? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var min = iterator.next() - while (iterator.hasNext()) { - val e = iterator.next() - if (comparator.compare(min, e) > 0) min = e - } - return min -} - -/** - * Returns `true` if the collection has no elements. - */ -public fun Iterable.none(): Boolean { - for (element in this) return false - return true -} - -/** - * Returns `true` if no elements match the given [predicate]. - */ -public inline fun Iterable.none(predicate: (T) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return false - return true -} - -/** - * Performs the given [action] on each element and returns the collection itself afterwards. - */ -@SinceKotlin("1.1") -public inline fun > C.onEach(action: (T) -> Unit): C { - return apply { for (element in this) action(element) } -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun Iterable.reduce(operation: (S, T) -> S): S { - val iterator = this.iterator() - if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.") - var accumulator: S = iterator.next() - while (iterator.hasNext()) { - accumulator = operation(accumulator, iterator.next()) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right - * to current accumulator value and each element with its index in the original collection. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself and calculates the next accumulator value. - */ -public inline fun Iterable.reduceIndexed(operation: (Int, S, T) -> S): S { - val iterator = this.iterator() - if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.") - var index = 1 - var accumulator: S = iterator.next() - while (iterator.hasNext()) { - accumulator = operation(index++, accumulator, iterator.next()) - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left to each element and current accumulator value. - */ -public inline fun List.reduceRight(operation: (T, S) -> S): S { - val iterator = listIterator(size) - if (!iterator.hasPrevious()) - throw UnsupportedOperationException("Empty list can't be reduced.") - var accumulator: S = iterator.previous() - while (iterator.hasPrevious()) { - accumulator = operation(iterator.previous(), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with last element and applying [operation] from right to left - * to each element with its index in the original list and current accumulator value. - * @param [operation] function that takes the index of an element, the element itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun List.reduceRightIndexed(operation: (Int, T, S) -> S): S { - val iterator = this.listIterator(size) - if (!iterator.hasPrevious()) - throw UnsupportedOperationException("Empty list can't be reduced.") - var accumulator: S = iterator.previous() - while (iterator.hasPrevious()) { - val index = iterator.previousIndex() - accumulator = operation(index, iterator.previous(), accumulator) - } - return accumulator -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the collection. - */ -public inline fun Iterable.sumBy(selector: (T) -> Int): Int { - var sum: Int = 0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the collection. - */ -public inline fun Iterable.sumByDouble(selector: (T) -> Double): Double { - var sum: Double = 0.0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns an original collection containing all the non-`null` elements, throwing an [IllegalArgumentException] if there are any `null` elements. - */ -public fun Iterable.requireNoNulls(): Iterable { - for (element in this) { - if (element == null) { - throw IllegalArgumentException("null element found in $this.") - } - } - @Suppress("UNCHECKED_CAST") - return this as Iterable -} - -/** - * Returns an original collection containing all the non-`null` elements, throwing an [IllegalArgumentException] if there are any `null` elements. - */ -public fun List.requireNoNulls(): List { - for (element in this) { - if (element == null) { - throw IllegalArgumentException("null element found in $this.") - } - } - @Suppress("UNCHECKED_CAST") - return this as List -} - -/** - * Splits this collection into a list of lists each not exceeding the given [size]. - * - * The last list in the resulting list may have less elements than the given [size]. - * - * @param size the number of elements to take in each list, must be positive and can be greater than the number of elements in this collection. - * - * @sample samples.collections.Collections.Transformations.chunked + * Each element in the list gets replaced with the [value]. */ @SinceKotlin("1.2") -public fun Iterable.chunked(size: Int): List> { - return windowed(size, size, partialWindows = true) +public actual fun MutableList.fill(value: T): Unit { + for (index in 0..lastIndex) { + this[index] = value + } } /** - * Splits this collection into several lists each not exceeding the given [size] - * and applies the given [transform] function to an each. + * Randomly shuffles elements in this list. * - * @return list of results of the [transform] applied to an each list. - * - * Note that the list passed to the [transform] function is ephemeral and is valid only inside that function. - * You should not store it or allow it to escape in some way, unless you made a snapshot of it. - * The last list may have less elements than the given [size]. - * - * @param size the number of elements to take in each list, must be positive and can be greater than the number of elements in this collection. - * - * @sample samples.text.Strings.chunkedTransform + * See: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm */ @SinceKotlin("1.2") -public fun Iterable.chunked(size: Int, transform: (List) -> R): List { - return windowed(size, size, partialWindows = true, transform = transform) -} - -/** - * Returns a list containing all elements of the original collection without the first occurrence of the given [element]. - */ -public operator fun Iterable.minus(element: T): List { - val result = ArrayList(collectionSizeOrDefault(10)) - var removed = false - return this.filterTo(result) { if (!removed && it == element) { removed = true; false } else true } -} - -/** - * Returns a list containing all elements of the original collection except the elements contained in the given [elements] array. - */ -public operator fun Iterable.minus(elements: Array): List { - if (elements.isEmpty()) return this.toList() - val other = elements.toHashSet() - return this.filterNot { it in other } -} - -/** - * Returns a list containing all elements of the original collection except the elements contained in the given [elements] collection. - */ -public operator fun Iterable.minus(elements: Iterable): List { - val other = elements.convertToSetForSetOperationWith(this) - if (other.isEmpty()) - return this.toList() - return this.filterNot { it in other } -} - -/** - * Returns a list containing all elements of the original collection except the elements contained in the given [elements] sequence. - */ -public operator fun Iterable.minus(elements: Sequence): List { - val other = elements.toHashSet() - if (other.isEmpty()) - return this.toList() - return this.filterNot { it in other } -} - -/** - * Returns a list containing all elements of the original collection without the first occurrence of the given [element]. - */ -@kotlin.internal.InlineOnly -public inline fun Iterable.minusElement(element: T): List { - return minus(element) -} - -/** - * Splits the original collection into pair of lists, - * where *first* list contains elements for which [predicate] yielded `true`, - * while *second* list contains elements for which [predicate] yielded `false`. - */ -public inline fun Iterable.partition(predicate: (T) -> Boolean): Pair, List> { - val first = ArrayList() - val second = ArrayList() - for (element in this) { - if (predicate(element)) { - first.add(element) - } else { - second.add(element) - } - } - return Pair(first, second) -} - -/** - * Returns a list containing all elements of the original collection and then the given [element]. - */ -public operator fun Iterable.plus(element: T): List { - if (this is Collection) return this.plus(element) - val result = ArrayList() - result.addAll(this) - result.add(element) - return result -} - -/** - * Returns a list containing all elements of the original collection and then the given [element]. - */ -public operator fun Collection.plus(element: T): List { - val result = ArrayList(size + 1) - result.addAll(this) - result.add(element) - return result -} - -/** - * Returns a list containing all elements of the original collection and then all elements of the given [elements] array. - */ -public operator fun Iterable.plus(elements: Array): List { - if (this is Collection) return this.plus(elements) - val result = ArrayList() - result.addAll(this) - result.addAll(elements) - return result -} - -/** - * Returns a list containing all elements of the original collection and then all elements of the given [elements] array. - */ -public operator fun Collection.plus(elements: Array): List { - val result = ArrayList(this.size + elements.size) - result.addAll(this) - result.addAll(elements) - return result -} - -/** - * Returns a list containing all elements of the original collection and then all elements of the given [elements] collection. - */ -public operator fun Iterable.plus(elements: Iterable): List { - if (this is Collection) return this.plus(elements) - val result = ArrayList() - result.addAll(this) - result.addAll(elements) - return result -} - -/** - * Returns a list containing all elements of the original collection and then all elements of the given [elements] collection. - */ -public operator fun Collection.plus(elements: Iterable): List { - if (elements is Collection) { - val result = ArrayList(this.size + elements.size) - result.addAll(this) - result.addAll(elements) - return result - } else { - val result = ArrayList(this) - result.addAll(elements) - return result +public actual fun MutableList.shuffle(): Unit { + for (i in lastIndex downTo 1) { + // FIXME: implement a good random + //val j = rand(i + 1) + val j = i / 2 + val copy = this[i] + this[i] = this[j] + this[j] = copy } } /** - * Returns a list containing all elements of the original collection and then all elements of the given [elements] sequence. - */ -public operator fun Iterable.plus(elements: Sequence): List { - val result = ArrayList() - result.addAll(this) - result.addAll(elements) - return result -} - -/** - * Returns a list containing all elements of the original collection and then all elements of the given [elements] sequence. - */ -public operator fun Collection.plus(elements: Sequence): List { - val result = ArrayList(this.size + 10) - result.addAll(this) - result.addAll(elements) - return result -} - -/** - * Returns a list containing all elements of the original collection and then the given [element]. - */ -@kotlin.internal.InlineOnly -public inline fun Iterable.plusElement(element: T): List { - return plus(element) -} - -/** - * Returns a list containing all elements of the original collection and then the given [element]. - */ -@kotlin.internal.InlineOnly -public inline fun Collection.plusElement(element: T): List { - return plus(element) -} - -/** - * Returns a list of snapshots of the window of the given [size] - * sliding along this collection with the given [step], where each - * snapshot is a list. - * - * Several last lists may have less elements than the given [size]. - * - * Both [size] and [step] must be positive and can be greater than the number of elements in this collection. - * @param size the number of elements to take in each window - * @param step the number of elements to move the window forward by on an each step, by default 1 - * @param partialWindows controls whether or not to keep partial windows in the end if any, - * by default `false` which means partial windows won't be preserved - * - * @sample samples.collections.Sequences.Transformations.takeWindows + * Returns a new list with the elements of this list randomly shuffled. */ @SinceKotlin("1.2") -public fun Iterable.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false): List> { - checkWindowSizeStep(size, step) - if (this is RandomAccess && this is List) { - val thisSize = this.size - val result = ArrayList>((thisSize + step - 1) / step) - var index = 0 - while (index < thisSize) { - val windowSize = size.coerceAtMost(thisSize - index) - if (windowSize < size && !partialWindows) break - result.add(List(windowSize) { this[it + index] }) - index += step - } - return result - } - val result = ArrayList>() - windowedIterator(iterator(), size, step, partialWindows, reuseBuffer = false).forEach { - result.add(it) - } - return result -} +public actual fun Iterable.shuffled(): List = toMutableList().apply { shuffle() } -/** - * Returns a list of results of applying the given [transform] function to - * an each list representing a view over the window of the given [size] - * sliding along this collection with the given [step]. - * - * Note that the list passed to the [transform] function is ephemeral and is valid only inside that function. - * You should not store it or allow it to escape in some way, unless you made a snapshot of it. - * Several last lists may have less elements than the given [size]. - * - * Both [size] and [step] must be positive and can be greater than the number of elements in this collection. - * @param size the number of elements to take in each window - * @param step the number of elements to move the window forward by on an each step, by default 1 - * @param partialWindows controls whether or not to keep partial windows in the end if any, - * by default `false` which means partial windows won't be preserved - * - * @sample samples.collections.Sequences.Transformations.averageWindows - */ -@SinceKotlin("1.2") -public fun Iterable.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false, transform: (List) -> R): List { - checkWindowSizeStep(size, step) - if (this is RandomAccess && this is List) { - val thisSize = this.size - val result = ArrayList((thisSize + step - 1) / step) - val window = MovingSubList(this) - var index = 0 - while (index < thisSize) { - window.move(index, (index + size).coerceAtMost(thisSize)) - if (!partialWindows && window.size < size) break - result.add(transform(window)) - index += step - } - return result - } - val result = ArrayList() - windowedIterator(iterator(), size, step, partialWindows, reuseBuffer = true).forEach { - result.add(transform(it)) - } - return result -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun Iterable.zip(other: Array): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -@Suppress("NOTHING_TO_INLINE") -inline fun min(x1: Int, x2: Int) = if (x1 < x2) x1 else x2 - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun Iterable.zip(other: Array, transform: (T, R) -> V): List { - val arraySize = other.size - val list = ArrayList(min(collectionSizeOrDefault(10), arraySize)) - var i = 0 - for (element in this) { - if (i >= arraySize) break - list.add(transform(element, other[i++])) - } - return list -} - -/** - * Returns a list of pairs built from elements of both collections with same indexes. List has length of shortest collection. - */ -public infix fun Iterable.zip(other: Iterable): List> { - return zip(other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a list of values built from elements of both collections with same indexes using provided [transform]. List has length of shortest collection. - */ -public inline fun Iterable.zip(other: Iterable, transform: (T, R) -> V): List { - val first = iterator() - val second = other.iterator() - val list = ArrayList(min(collectionSizeOrDefault(10), other.collectionSizeOrDefault(10))) - while (first.hasNext() && second.hasNext()) { - list.add(transform(first.next(), second.next())) - } - return list -} - -/** - * Returns a list of pairs of each two adjacent elements in this collection. - * - * The returned list is empty if this collection contains less than two elements. - * - * @sample samples.collections.Collections.Transformations.zipWithNext - */ -@SinceKotlin("1.2") -public fun Iterable.zipWithNext(): List> { - return zipWithNext { a, b -> a to b } -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to an each pair of two adjacent elements in this collection. - * - * The returned list is empty if this collection contains less than two elements. - * - * @sample samples.collections.Collections.Transformations.zipWithNextToFindDeltas - */ -@SinceKotlin("1.2") -public inline fun Iterable.zipWithNext(transform: (a: T, b: T) -> R): List { - val iterator = iterator() - if (!iterator.hasNext()) return emptyList() - val result = mutableListOf() - var current = iterator.next() - while (iterator.hasNext()) { - val next = iterator.next() - result.add(transform(current, next)) - current = next - } - return result -} - -/** - * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun Iterable.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): A { - buffer.append(prefix) - var count = 0 - for (element in this) { - if (++count > 1) buffer.append(separator) - if (limit < 0 || count <= limit) { - if (transform != null) - buffer.append(transform(element)) - else - buffer.append(if (element == null) "null" else element.toString()) - } else break - } - if (limit >= 0 && count > limit) buffer.append(truncated) - buffer.append(postfix) - return buffer -} - -/** - * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun Iterable.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String { - return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() -} - -/** - * Returns this collection as an [Iterable]. - */ -@kotlin.internal.InlineOnly -public inline fun Iterable.asIterable(): Iterable { - return this -} - -/** - * Creates a [Sequence] instance that wraps the original collection returning its elements when being iterated. - */ -public fun Iterable.asSequence(): Sequence { - return Sequence { this.iterator() } -} - -/** - * Returns a list containing all elements that are instances of specified class. - */ -//public fun Iterable<*>.filterIsInstance(klass: Class): List { -// return filterIsInstanceTo(ArrayList(), klass) -//} - -/** - * Returns an average value of elements in the collection. - */ -public fun Iterable.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the collection. - */ -public fun Iterable.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the collection. - */ -public fun Iterable.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the collection. - */ -public fun Iterable.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the collection. - */ -public fun Iterable.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns an average value of elements in the collection. - */ -public fun Iterable.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) Double.NaN else sum / count -} - -/** - * Returns the sum of all elements in the collection. - */ -public fun Iterable.sum(): Int { - var sum: Int = 0 - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the collection. - */ -public fun Iterable.sum(): Int { - var sum: Int = 0 - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the collection. - */ -public fun Iterable.sum(): Int { - var sum: Int = 0 - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the collection. - */ -public fun Iterable.sum(): Long { - var sum: Long = 0L - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the collection. - */ -public fun Iterable.sum(): Float { - var sum: Float = 0.0f - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the collection. - */ -public fun Iterable.sum(): Double { - var sum: Double = 0.0 - for (element in this) { - sum += element - } - return sum -} diff --git a/runtime/src/main/kotlin/kotlin/collections/Grouping.kt b/runtime/src/main/kotlin/kotlin/collections/Grouping.kt deleted file mode 100644 index 4eec8d79817..00000000000 --- a/runtime/src/main/kotlin/kotlin/collections/Grouping.kt +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.collections - -/** - * Represents a source of elements with a [keyOf] function, which can be applied to each element to get its key. - * - * A [Grouping] structure serves as an intermediate step in group-and-fold operations: - * they group elements by their keys and then fold each group with some aggregating operation. - * - * It is created by attaching `keySelector: (T) -> K` function to a source of elements. - * To get an instance of [Grouping] use one of `groupingBy` extension functions: - * - [Iterable.groupingBy] - * - [Sequence.groupingBy] - * - [Array.groupingBy] - * - [CharSequence.groupingBy] - * - * For the list of group-and-fold operations available, see the [extension functions](#extension-functions) for `Grouping`. - */ -@SinceKotlin("1.1") -public interface Grouping { - /** Returns an [Iterator] over the elements of the source of this grouping. */ - fun sourceIterator(): Iterator - /** Extracts the key of an [element]. */ - fun keyOf(element: T): K -} - -/** - * Groups elements from the [Grouping] source by key and applies [operation] to the elements of each group sequentially, - * passing the previously accumulated value and the current element as arguments, and stores the results in a new map. - * - * The key for each element is provided by the [Grouping.keyOf] function. - * - * @param operation function is invoked on each element with the following parameters: - * - `key`: the key of the group this element belongs to; - * - `accumulator`: the current value of the accumulator of the group, can be `null` if it's the first `element` encountered in the group; - * - `element`: the element from the source being aggregated; - * - `first`: indicates whether it's the first `element` encountered in the group. - * - * @return a [Map] associating the key of each group with the result of aggregation of the group elements. - */ -@SinceKotlin("1.1") -public inline fun Grouping.aggregate( - operation: (key: K, accumulator: R?, element: T, first: Boolean) -> R -): Map { - return aggregateTo(mutableMapOf(), operation) -} - -/** - * Groups elements from the [Grouping] source by key and applies [operation] to the elements of each group sequentially, - * passing the previously accumulated value and the current element as arguments, - * and stores the results in the given [destination] map. - * - * The key for each element is provided by the [Grouping.keyOf] function. - * - * @param operation a function that is invoked on each element with the following parameters: - * - `key`: the key of the group this element belongs to; - * - `accumulator`: the current value of the accumulator of the group, can be `null` if it's the first `element` encountered in the group; - * - `element`: the element from the source being aggregated; - * - `first`: indicates whether it's the first `element` encountered in the group. - * - * If the [destination] map already has a value corresponding to some key, - * then the elements being aggregated for that key are never considered as `first`. - * - * @return the [destination] map associating the key of each group with the result of aggregation of the group elements. - */ -@SinceKotlin("1.1") -public inline fun > Grouping.aggregateTo( - destination: M, - operation: (key: K, accumulator: R?, element: T, first: Boolean) -> R -): M { - for (e in this.sourceIterator()) { - val key = keyOf(e) - val accumulator = destination[key] - destination[key] = operation(key, accumulator, e, accumulator == null && !destination.containsKey(key)) - } - return destination -} - -/** - * Groups elements from the [Grouping] source by key and applies [operation] to the elements of each group sequentially, - * passing the previously accumulated value and the current element as arguments, and stores the results in a new map. - * An initial value of accumulator is provided by [initialValueSelector] function. - * - * @param initialValueSelector a function that provides an initial value of accumulator for each group. - * It's invoked with parameters: - * - `key`: the key of the group; - * - `element`: the first element being encountered in that group. - * - * @param operation a function that is invoked on each element with the following parameters: - * - `key`: the key of the group this element belongs to; - * - `accumulator`: the current value of the accumulator of the group; - * - `element`: the element from the source being accumulated. - * - * @return a [Map] associating the key of each group with the result of accumulating the group elements. - */ -@SinceKotlin("1.1") -@Suppress("UNCHECKED_CAST") -public inline fun Grouping.fold( - initialValueSelector: (key: K, element: T) -> R, - operation: (key: K, accumulator: R, element: T) -> R -): Map = - aggregate { key, acc, e, first -> operation(key, if (first) initialValueSelector(key, e) else acc as R, e) } - -/** - * Groups elements from the [Grouping] source by key and applies [operation] to the elements of each group sequentially, - * passing the previously accumulated value and the current element as arguments, - * and stores the results in the given [destination] map. - * An initial value of accumulator is provided by [initialValueSelector] function. - * - * @param initialValueSelector a function that provides an initial value of accumulator for each group. - * It's invoked with parameters: - * - `key`: the key of the group; - * - `element`: the first element being encountered in that group. - * - * If the [destination] map already has a value corresponding to some key, that value is used as an initial value of - * the accumulator for that group and the [initialValueSelector] function is not called for that group. - * - * @param operation a function that is invoked on each element with the following parameters: - * - `key`: the key of the group this element belongs to; - * - `accumulator`: the current value of the accumulator of the group; - * - `element`: the element from the source being accumulated. - * - * @return the [destination] map associating the key of each group with the result of accumulating the group elements. - */ -@SinceKotlin("1.1") -@Suppress("UNCHECKED_CAST") -public inline fun > Grouping.foldTo( - destination: M, - initialValueSelector: (key: K, element: T) -> R, - operation: (key: K, accumulator: R, element: T) -> R -): M = - aggregateTo(destination) { key, acc, e, first -> operation(key, if (first) initialValueSelector(key, e) else acc as R, e) } - - -/** - * Groups elements from the [Grouping] source by key and applies [operation] to the elements of each group sequentially, - * passing the previously accumulated value and the current element as arguments, and stores the results in a new map. - * An initial value of accumulator is the same [initialValue] for each group. - * - * @param operation a function that is invoked on each element with the following parameters: - * - `accumulator`: the current value of the accumulator of the group; - * - `element`: the element from the source being accumulated. - * - * @return a [Map] associating the key of each group with the result of accumulating the group elements. - */ -@SinceKotlin("1.1") -@Suppress("UNCHECKED_CAST") -public inline fun Grouping.fold( - initialValue: R, - operation: (accumulator: R, element: T) -> R -): Map = - aggregate { _, acc, e, first -> operation(if (first) initialValue else acc as R, e) } - -/** - * Groups elements from the [Grouping] source by key and applies [operation] to the elements of each group sequentially, - * passing the previously accumulated value and the current element as arguments, - * and stores the results in the given [destination] map. - * An initial value of accumulator is the same [initialValue] for each group. - * - * If the [destination] map already has a value corresponding to the key of some group, - * that value is used as an initial value of the accumulator for that group. - * - * @param operation a function that is invoked on each element with the following parameters: - * - `accumulator`: the current value of the accumulator of the group; - * - `element`: the element from the source being accumulated. - * - * @return the [destination] map associating the key of each group with the result of accumulating the group elements. - */ -@SinceKotlin("1.1") -@Suppress("UNCHECKED_CAST") -public inline fun > Grouping.foldTo( - destination: M, - initialValue: R, - operation: (accumulator: R, element: T) -> R -): M = - aggregateTo(destination) { _, acc, e, first -> operation(if (first) initialValue else acc as R, e) } - - -/** - * Groups elements from the [Grouping] source by key and applies the reducing [operation] to the elements of each group - * sequentially starting from the second element of the group, - * passing the previously accumulated value and the current element as arguments, - * and stores the results in a new map. - * An initial value of accumulator is the first element of the group. - * - * @param operation a function that is invoked on each subsequent element of the group with the following parameters: - * - `key`: the key of the group this element belongs to; - * - `accumulator`: the current value of the accumulator of the group; - * - `element`: the element from the source being accumulated. - * - * @return a [Map] associating the key of each group with the result of accumulating the group elements. - */ -@SinceKotlin("1.1") -@Suppress("UNCHECKED_CAST") -public inline fun Grouping.reduce( - operation: (key: K, accumulator: S, element: T) -> S -): Map = - aggregate { key, acc, e, first -> - if (first) e else operation(key, acc as S, e) - } - -/** - * Groups elements from the [Grouping] source by key and applies the reducing [operation] to the elements of each group - * sequentially starting from the second element of the group, - * passing the previously accumulated value and the current element as arguments, - * and stores the results in the given [destination] map. - * An initial value of accumulator is the first element of the group. - * - * If the [destination] map already has a value corresponding to the key of some group, - * that value is used as an initial value of the accumulator for that group and the first element of that group is also - * subjected to the [operation]. - - * @param operation a function that is invoked on each subsequent element of the group with the following parameters: - * - `accumulator`: the current value of the accumulator of the group; - * - `element`: the element from the source being folded; - * - * @return the [destination] map associating the key of each group with the result of accumulating the group elements. - */ -@SinceKotlin("1.1") -@Suppress("UNCHECKED_CAST") -public inline fun > Grouping.reduceTo( - destination: M, - operation: (key: K, accumulator: S, element: T) -> S -): M = - aggregateTo(destination) { key, acc, e, first -> - if (first) e else operation(key, acc as S, e) - } - -/** - * Groups elements from the [Grouping] source by key and counts elements in each group. - * - * @return a [Map] associating the key of each group with the count of elements in the group. - * - * @sample samples.collections.Collections.Transformations.groupingByEachCount - */ -@SinceKotlin("1.1") -public fun Grouping.eachCount(): Map = eachCountTo(mutableMapOf()) - -/** - * Groups elements from the [Grouping] source by key and counts elements in each group to the given [destination] map. - * - * If the [destination] map already has a value corresponding to the key of some group, - * that value is used as an initial value of the counter for that group. - * - * @return the [destination] map associating the key of each group with the count of elements in the group. - * - * @sample samples.collections.Collections.Transformations.groupingByEachCount - */ -@SinceKotlin("1.1") -public fun > Grouping.eachCountTo(destination: M): M = - foldTo(destination, 0) { acc, _ -> acc + 1 } - diff --git a/runtime/src/main/kotlin/kotlin/collections/HashMap.kt b/runtime/src/main/kotlin/kotlin/collections/HashMap.kt index 0330e5eea17..ac505c6bb0b 100644 --- a/runtime/src/main/kotlin/kotlin/collections/HashMap.kt +++ b/runtime/src/main/kotlin/kotlin/collections/HashMap.kt @@ -16,7 +16,7 @@ package kotlin.collections -class HashMap private constructor( +actual class HashMap private constructor( private var keysArray: Array, private var valuesArray: Array?, // allocated only when actually used, always null in pure HashSet private var presenceArray: IntArray, @@ -26,8 +26,9 @@ class HashMap private constructor( ) : MutableMap { private var hashShift: Int = computeShift(hashSize) - override var size: Int = 0 - private set + private var _size: Int = 0 + override actual val size: Int + get() = _size private var keysView: HashSet? = null private var valuesView: HashMapValues? = null @@ -35,36 +36,39 @@ class HashMap private constructor( // ---------------------------- functions ---------------------------- - constructor() : this(INITIAL_CAPACITY) + actual constructor() : this(INITIAL_CAPACITY) - constructor(capacity: Int) : this( - arrayOfUninitializedElements(capacity), + actual constructor(initialCapacity: Int) : this( + arrayOfUninitializedElements(initialCapacity), null, - IntArray(capacity), - IntArray(computeHashSize(capacity)), + IntArray(initialCapacity), + IntArray(computeHashSize(initialCapacity)), INITIAL_MAX_PROBE_DISTANCE, 0) - constructor(m: Map) : this(m.size) { - putAll(m) + actual constructor(original: Map) : this(original.size) { + putAll(original) } - override fun isEmpty(): Boolean = size == 0 - override fun containsKey(key: K): Boolean = findKey(key) >= 0 - override fun containsValue(value: V): Boolean = findValue(value) >= 0 + // This implementation doesn't use a loadFactor, this constructor is used for compatibility with common stdlib + actual constructor(initialCapacity: Int, loadFactor: Float) : this(initialCapacity) + + override actual fun isEmpty(): Boolean = _size == 0 + override actual fun containsKey(key: K): Boolean = findKey(key) >= 0 + override actual fun containsValue(value: V): Boolean = findValue(value) >= 0 operator fun set(key: K, value: V): Unit { put(key, value) } - override operator fun get(key: K): V? { + override actual operator fun get(key: K): V? { val index = findKey(key) if (index < 0) return null return valuesArray!![index] } - override fun put(key: K, value: V): V? { + override actual fun put(key: K, value: V): V? { val index = addKey(key) val valuesArray = allocateValuesArray() if (index < 0) { @@ -77,11 +81,11 @@ class HashMap private constructor( } } - override fun putAll(from: Map) { + override actual fun putAll(from: Map) { putAllEntries(from.entries) } - override fun remove(key: K): V? { + override actual fun remove(key: K): V? { val index = removeKey(key) if (index < 0) return null val valuesArray = valuesArray!! @@ -90,7 +94,7 @@ class HashMap private constructor( return oldValue } - override fun clear() { + override actual fun clear() { // O(length) implementation for hashArray cleanup for (i in 0..length - 1) { val hash = presenceArray[i] @@ -101,11 +105,11 @@ class HashMap private constructor( } keysArray.resetRange(0, length) valuesArray?.resetRange(0, length) - size = 0 + _size = 0 length = 0 } - override val keys: MutableSet get() { + override actual val keys: MutableSet get() { val cur = keysView return if (cur == null) { val new = HashSet(this) @@ -114,7 +118,7 @@ class HashMap private constructor( } else cur } - override val values: MutableCollection get() { + override actual val values: MutableCollection get() { val cur = valuesView return if (cur == null) { val new = HashMapValues(this) @@ -123,7 +127,7 @@ class HashMap private constructor( } else cur } - override val entries: MutableSet> get() { + override actual val entries: MutableSet> get() { val cur = entriesView return if (cur == null) { val new = HashMapEntrySet(this) @@ -148,7 +152,7 @@ class HashMap private constructor( } override fun toString(): String { - val sb = StringBuilder(2 + size * 3) + val sb = StringBuilder(2 + _size * 3) sb.append("{") var i = 0 val it = entriesIterator() @@ -179,7 +183,7 @@ class HashMap private constructor( presenceArray = presenceArray.copyOfUninitializedElements(newSize) val newHashSize = computeHashSize(newSize) if (newHashSize > hashSize) rehash(newHashSize) - } else if (length + capacity - size > this.capacity) { + } else if (length + capacity - _size > this.capacity) { rehash(hashSize) } } @@ -213,7 +217,7 @@ class HashMap private constructor( } private fun rehash(newHashSize: Int) { - if (length > size) compact() + if (length > _size) compact() if (newHashSize != hashSize) { hashArray = IntArray(newHashSize) hashShift = computeShift(newHashSize) @@ -282,7 +286,7 @@ class HashMap private constructor( keysArray[putIndex] = key presenceArray[putIndex] = hash hashArray[hash] = putIndex + 1 - size++ + _size++ if (probeDistance > maxProbeDistance) maxProbeDistance = probeDistance return putIndex } @@ -309,7 +313,7 @@ class HashMap private constructor( keysArray.resetAt(index) removeHashAt(presenceArray[index]) presenceArray[index] = TOMBSTONE - size-- + _size-- } private fun removeHashAt(removedHash: Int) { @@ -386,7 +390,7 @@ class HashMap private constructor( } } - private fun contentEquals(other: Map<*, *>): Boolean = size == other.size && containsAllEntries(other.entries) + private fun contentEquals(other: Map<*, *>): Boolean = _size == other.size && containsAllEntries(other.entries) internal fun containsAllEntries(m: Collection>): Boolean { val it = m.iterator() @@ -702,4 +706,4 @@ internal class HashMapEntrySet internal constructor( } // This hash map keeps insertion order. -typealias LinkedHashMap = HashMap \ No newline at end of file +actual typealias LinkedHashMap = HashMap \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/collections/HashSet.kt b/runtime/src/main/kotlin/kotlin/collections/HashSet.kt index 47e3140cb3a..b3b69403bce 100644 --- a/runtime/src/main/kotlin/kotlin/collections/HashSet.kt +++ b/runtime/src/main/kotlin/kotlin/collections/HashSet.kt @@ -16,28 +16,31 @@ package kotlin.collections -class HashSet internal constructor( - val backing: HashMap -) : MutableSet, AbstractMutableCollection(), konan.internal.KonanSet { +actual class HashSet internal constructor( + val backing: HashMap +) : MutableSet, AbstractMutableCollection(), konan.internal.KonanSet { - constructor() : this(HashMap()) + actual constructor() : this(HashMap()) - constructor(capacity: Int) : this(HashMap(capacity)) + actual constructor(initialCapacity: Int) : this(HashMap(initialCapacity)) - constructor(c: Collection) : this(c.size) { - addAll(c) + actual constructor(elements: Collection) : this(elements.size) { + addAll(elements) } - override val size: Int get() = backing.size - override fun isEmpty(): Boolean = backing.isEmpty() - override fun contains(element: K): Boolean = backing.containsKey(element) - override fun getElement(element: K): K? = backing.getKey(element) - override fun clear() = backing.clear() - override fun add(element: K): Boolean = backing.addKey(element) >= 0 - override fun remove(element: K): Boolean = backing.removeKey(element) >= 0 - override fun iterator(): MutableIterator = backing.keysIterator() + // This implementation doesn't use a loadFactor + actual constructor(initialCapacity: Int, loadFactor: Float) : this(initialCapacity) - override fun containsAll(elements: Collection): Boolean { + override actual val size: Int get() = backing.size + override actual fun isEmpty(): Boolean = backing.isEmpty() + override actual fun contains(element: E): Boolean = backing.containsKey(element) + override fun getElement(element: E): E? = backing.getKey(element) + override actual fun clear() = backing.clear() + override actual fun add(element: E): Boolean = backing.addKey(element) >= 0 + override actual fun remove(element: E): Boolean = backing.removeKey(element) >= 0 + override actual fun iterator(): MutableIterator = backing.keysIterator() + + override actual fun containsAll(elements: Collection): Boolean { val it = elements.iterator() while (it.hasNext()) { if (!contains(it.next())) @@ -46,7 +49,7 @@ class HashSet internal constructor( return true } - override fun addAll(elements: Collection): Boolean { + override actual fun addAll(elements: Collection): Boolean { val it = elements.iterator() var updated = false while (it.hasNext()) { @@ -60,7 +63,7 @@ class HashSet internal constructor( return other === this || (other is Set<*>) && contentEquals( - @Suppress("UNCHECKED_CAST") (other as Set)) + @Suppress("UNCHECKED_CAST") (other as Set)) } override fun hashCode(): Int { @@ -76,8 +79,8 @@ class HashSet internal constructor( // ---------------------------- private ---------------------------- - private fun contentEquals(other: Set): Boolean = size == other.size && containsAll(other) + private fun contentEquals(other: Set): Boolean = size == other.size && containsAll(other) } // This hash set keeps insertion order. -typealias LinkedHashSet = HashSet \ No newline at end of file +actual typealias LinkedHashSet = HashSet \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/collections/Iterables.kt b/runtime/src/main/kotlin/kotlin/collections/Iterables.kt deleted file mode 100644 index 7ca467c1945..00000000000 --- a/runtime/src/main/kotlin/kotlin/collections/Iterables.kt +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.collections - -/** - * Given an [iterator] function constructs an [Iterable] instance that returns values through the [Iterator] - * provided by that function. - */ -@kotlin.internal.InlineOnly -public inline fun Iterable(crossinline iterator: () -> Iterator): Iterable = object : Iterable { - override fun iterator(): Iterator = iterator() -} - -/** - * A wrapper over another [Iterable] (or any other object that can produce an [Iterator]) that returns - * an indexing iterator. - */ -internal class IndexingIterable(private val iteratorFactory: () -> Iterator) : Iterable> { - override fun iterator(): Iterator> = IndexingIterator(iteratorFactory()) -} - - -/** - * Returns the size of this iterable if it is known, or `null` otherwise. - */ -@PublishedApi -internal fun Iterable.collectionSizeOrNull(): Int? = if (this is Collection<*>) this.size else null - -/** - * Returns the size of this iterable if it is known, or the specified [default] value otherwise. - */ -@PublishedApi -internal fun Iterable.collectionSizeOrDefault(default: Int): Int = if (this is Collection<*>) this.size else default - -/** Returns true when it's safe to convert this collection to a set without changing contains method behavior. */ -private fun Collection.safeToConvertToSet() = size > 2 && this is ArrayList - -/** Converts this collection to a set, when it's worth so and it doesn't change contains method behavior. */ -internal fun Iterable.convertToSetForSetOperationWith(source: Iterable): Collection = - when(this) { - is Set -> this - is Collection -> - when { - source is Collection && source.size < 2 -> this - else -> if (this.safeToConvertToSet()) toHashSet() else this - } - else -> toHashSet() - } - -/** Converts this collection to a set, when it's worth so and it doesn't change contains method behavior. */ -internal fun Iterable.convertToSetForSetOperation(): Collection = - when(this) { - is Set -> this - is Collection -> if (this.safeToConvertToSet()) toHashSet() else this - else -> toHashSet() - } - - -/** - * Returns a single list of all elements from all collections in the given collection. - */ -public fun Iterable>.flatten(): List { - val result = ArrayList() - for (element in this) { - result.addAll(element) - } - return result -} - -/** - * Returns a pair of lists, where - * *first* list is built from the first values of each pair from this collection, - * *second* list is built from the second values of each pair from this collection. - */ -public fun Iterable>.unzip(): Pair, List> { - val expectedSize = collectionSizeOrDefault(10) - val listT = ArrayList(expectedSize) - val listR = ArrayList(expectedSize) - for (pair in this) { - listT.add(pair.first) - listR.add(pair.second) - } - return listT to listR -} diff --git a/runtime/src/main/kotlin/kotlin/collections/Iterators.kt b/runtime/src/main/kotlin/kotlin/collections/Iterators.kt index a68b4e04a26..f80c87faf25 100644 --- a/runtime/src/main/kotlin/kotlin/collections/Iterators.kt +++ b/runtime/src/main/kotlin/kotlin/collections/Iterators.kt @@ -79,31 +79,3 @@ public abstract class BooleanIterator : Iterator { /** Returns the next value in the sequence without boxing. */ public abstract fun nextBoolean(): Boolean } - -/** - * Returns the given iterator itself. This allows to use an instance of iterator in a `for` loop. - */ -@kotlin.internal.InlineOnly -public inline operator fun Iterator.iterator(): Iterator = this - -/** - * Returns an [Iterator] wrapping each value produced by this [Iterator] with the [IndexedValue], - * containing value and it's index. - */ -public fun Iterator.withIndex(): Iterator> = IndexingIterator(this) - -/** - * Performs the given [operation] on each element of this [Iterator]. - */ -public inline fun Iterator.forEach(operation: (T) -> Unit) : Unit { - for (element in this) operation(element) -} - -/** - * Iterator transforming original `iterator` into iterator of [IndexedValue], counting index from zero. - */ -internal class IndexingIterator(private val iterator: Iterator) : Iterator> { - private var index = 0 - final override fun hasNext(): Boolean = iterator.hasNext() - final override fun next(): IndexedValue = IndexedValue(index++, iterator.next()) -} \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/collections/MapAccessors.kt b/runtime/src/main/kotlin/kotlin/collections/MapAccessors.kt deleted file mode 100644 index 373efe65ad4..00000000000 --- a/runtime/src/main/kotlin/kotlin/collections/MapAccessors.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.collections - -import kotlin.reflect.KProperty -import kotlin.internal.Exact - -/** - * Returns the value of the property for the given object from this read-only map. - * @param thisRef the object for which the value is requested (not used). - * @param property the metadata for the property, used to get the name of property and lookup the value corresponding to this name in the map. - * @return the property value. - * - * @throws NoSuchElementException when the map doesn't contain value for the property name and doesn't provide an implicit default (see [withDefault]). - */ -@kotlin.internal.InlineOnly -public inline operator fun Map.getValue(thisRef: Any?, property: KProperty<*>): V1 - = @Suppress("UNCHECKED_CAST", "NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") (getOrImplicitDefault(property.name) as V1) - -/** - * Returns the value of the property for the given object from this mutable map. - * @param thisRef the object for which the value is requested (not used). - * @param property the metadata for the property, used to get the name of property and lookup the value corresponding to this name in the map. - * @return the property value. - * - * @throws NoSuchElementException when the map doesn't contain value for the property name and doesn't provide an implicit default (see [withDefault]). - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableMap.getValue(thisRef: Any?, property: KProperty<*>): V - = @Suppress("UNCHECKED_CAST", "NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") (getOrImplicitDefault(property.name) as V) - -/** - * Stores the value of the property for the given object in this mutable map. - * @param thisRef the object for which the value is requested (not used). - * @param property the metadata for the property, used to get the name of property and store the value associated with that name in the map. - * @param value the value to set. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableMap.setValue(thisRef: Any?, property: KProperty<*>, value: V) { - this.put(property.name, value) -} diff --git a/runtime/src/main/kotlin/kotlin/collections/MapWithDefault.kt b/runtime/src/main/kotlin/kotlin/collections/MapWithDefault.kt deleted file mode 100644 index 956034c5a21..00000000000 --- a/runtime/src/main/kotlin/kotlin/collections/MapWithDefault.kt +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.collections - -/** - * Returns the value for the given key, or the implicit default value for this map. - * By default no implicit value is provided for maps and a [NoSuchElementException] is thrown. - * To create a map with implicit default value use [withDefault] method. - * - * @throws NoSuchElementException when the map doesn't contain a value for the specified key and no implicit default was provided for that map. - */ -@PublishedApi -internal fun Map.getOrImplicitDefault(key: K): V { - if (this is MapWithDefault) - return this.getOrImplicitDefault(key) - - return getOrElseNullable(key, { throw NoSuchElementException("Key $key is missing in the map.") }) -} - -/** - * Returns a wrapper of this read-only map, having the implicit default value provided with the specified function [defaultValue]. - * This implicit default value is used when properties are delegated to the returned map, - * and that map doesn't contain a value for the key specified. - * - * When this map already has an implicit default value provided with a former call to [withDefault], it is being replaced by this call. - */ -public fun Map.withDefault(defaultValue: (key: K) -> V): Map = - when (this) { - is MapWithDefault -> this.map.withDefault(defaultValue) - else -> MapWithDefaultImpl(this, defaultValue) - } - -/** - * Returns a wrapper of this mutable map, having the implicit default value provided with the specified function [defaultValue]. - * This implicit default value is used when properties are delegated to the returned map, - * and that map doesn't contain a value for the key specified. - * - * When this map already has an implicit default value provided with a former call to [withDefault], it is being replaced by this call. - */ -public fun MutableMap.withDefault(defaultValue: (key: K) -> V): MutableMap = - when (this) { - is MutableMapWithDefault -> this.map.withDefault(defaultValue) - else -> MutableMapWithDefaultImpl(this, defaultValue) - } - - - - - -private interface MapWithDefault: Map { - public val map: Map - public fun getOrImplicitDefault(key: K): V -} - -private interface MutableMapWithDefault: MutableMap, MapWithDefault { - public override val map: MutableMap -} - - -private class MapWithDefaultImpl(public override val map: Map, private val default: (key: K) -> V) : MapWithDefault { - override fun equals(other: Any?): Boolean = map.equals(other) - override fun hashCode(): Int = map.hashCode() - override fun toString(): String = map.toString() - override val size: Int get() = map.size - override fun isEmpty(): Boolean = map.isEmpty() - override fun containsKey(key: K): Boolean = map.containsKey(key) - override fun containsValue(value: @UnsafeVariance V): Boolean = map.containsValue(value) - override fun get(key: K): V? = map.get(key) - override val keys: Set get() = map.keys - override val values: Collection get() = map.values - override val entries: Set> get() = map.entries - - override fun getOrImplicitDefault(key: K): V = map.getOrElseNullable(key, { default(key) }) -} - -private class MutableMapWithDefaultImpl(public override val map: MutableMap, private val default: (key: K) -> V): MutableMapWithDefault { - override fun equals(other: Any?): Boolean = map.equals(other) - override fun hashCode(): Int = map.hashCode() - override fun toString(): String = map.toString() - override val size: Int get() = map.size - override fun isEmpty(): Boolean = map.isEmpty() - override fun containsKey(key: K): Boolean = map.containsKey(key) - override fun containsValue(value: @UnsafeVariance V): Boolean = map.containsValue(value) - override fun get(key: K): V? = map.get(key) - override val keys: MutableSet get() = map.keys - override val values: MutableCollection get() = map.values - override val entries: MutableSet> get() = map.entries - - override fun put(key: K, value: V): V? = map.put(key, value) - override fun remove(key: K): V? = map.remove(key) - override fun putAll(from: Map) = map.putAll(from) - override fun clear() = map.clear() - - override fun getOrImplicitDefault(key: K): V = map.getOrElseNullable(key, { default(key) }) -} - diff --git a/runtime/src/main/kotlin/kotlin/collections/Maps.kt b/runtime/src/main/kotlin/kotlin/collections/Maps.kt index 2cfd43ba3f5..98d84e841ac 100644 --- a/runtime/src/main/kotlin/kotlin/collections/Maps.kt +++ b/runtime/src/main/kotlin/kotlin/collections/Maps.kt @@ -16,863 +16,9 @@ package kotlin.collections -private object EmptyMap : Map { - override fun equals(other: Any?): Boolean = other is Map<*,*> && other.isEmpty() - override fun hashCode(): Int = 0 - override fun toString(): String = "{}" - - override val size: Int get() = 0 - override fun isEmpty(): Boolean = true - - override fun containsKey(key: Any?): Boolean = false - override fun containsValue(value: Nothing): Boolean = false - override fun get(key: Any?): Nothing? = null - override val entries: Set> get() = EmptySet - override val keys: Set get() = EmptySet - override val values: Collection get() = EmptyList - - private fun readResolve(): Any = EmptyMap -} - -/** - * Returns an empty read-only map of specified type. The returned map is serializable (JVM). - * @sample samples.collections.Maps.Instantiation.emptyReadOnlyMap - */ -@Suppress("UNCHECKED_CAST") -public fun emptyMap(): Map = EmptyMap as Map - -/** - * Returns a new read-only map with the specified contents, given as a list of pairs - * where the first value is the key and the second is the value. If multiple pairs have - * the same key, the resulting map will contain the value from the last of those pairs. - * - * Entries of the map are iterated in the order they were specified. - * The returned map is serializable (JVM). - * - * @sample samples.collections.Maps.Instantiation.mapFromPairs - */ -public fun mapOf(vararg pairs: Pair): Map = - if (pairs.size > 0) hashMapOf(*pairs) else emptyMap() - -/** - * Returns an empty read-only map. The returned map is serializable (JVM). - * @sample samples.collections.Maps.Instantiation.emptyReadOnlyMap - */ -@kotlin.internal.InlineOnly -public inline fun mapOf(): Map = emptyMap() - -// TODO: Add a singleton map class (see Kotlin JVM mapOf(Pair) implementation). -/** - * Returns an immutable map, mapping only the specified key to the - * specified value. The returned map is serializable. - * @sample samples.collections.Maps.Instantiation.mapFromPairs - */ -public fun mapOf(pair: Pair): Map = hashMapOf(pair) - -/** - * Returns a new [MutableMap] with the specified contents, given as a list of pairs - * where the first component is the key and the second is the value. If multiple pairs have - * the same key, the resulting map will contain the value from the last of those pairs. - * Entries of the map are iterated in the order they were specified. - * @sample samples.collections.Maps.Instantiation.mutableMapFromPairs - * @sample samples.collections.Maps.Instantiation.emptyMutableMap - */ -public fun mutableMapOf(vararg pairs: Pair): MutableMap - = HashMap(mapCapacity(pairs.size)).apply { putAll(pairs) } - -/** - * Returns a new [HashMap] with the specified contents, given as a list of pairs - * where the first component is the key and the second is the value. - * - * @sample samples.collections.Maps.Instantiation.hashMapFromPairs - */ -public fun hashMapOf(vararg pairs: Pair): HashMap - = HashMap(mapCapacity(pairs.size)).apply { putAll(pairs) } - -/** - * Returns a new [HashMap] with the specified contents, given as a list of pairs - * where the first component is the key and the second is the value. If multiple pairs have - * the same key, the resulting map will contain the value from the last of those pairs. - * Entries of the map are iterated in the order they were specified. - * - * @sample samples.collections.Maps.Instantiation.linkedMapFromPairs - */ -public fun linkedMapOf(vararg pairs: Pair): LinkedHashMap - = LinkedHashMap(mapCapacity(pairs.size)).apply { putAll(pairs) } - -/** - * Calculate the initial capacity of a map, based on Guava's com.google.common.collect.Maps approach. This is equivalent - * to the Collection constructor for HashSet, (c.size()/.75f) + 1, but provides further optimisations for very small or - * very large sizes, allows support non-collection classes, and provides consistency for all map based class construction. - */ -@PublishedApi -internal fun mapCapacity(expectedSize: Int): Int { - if (expectedSize < 3) { - return expectedSize + 1 - } - if (expectedSize < 0x40000000 /* INT_MAX_POWER_OF_TWO */) { - return expectedSize + expectedSize / 3 - } - return 0x7fffffff // any large value -} - -// Using global constant with dependency like that introduces weird init order dependencies. -// private const val INT_MAX_POWER_OF_TWO: Int = Int.MAX_VALUE / 2 + 1 - -/** Returns `true` if this map is not empty. */ -@kotlin.internal.InlineOnly -public inline fun Map.isNotEmpty(): Boolean = !isEmpty() - -/** - * Returns the [Map] if its not `null`, or the empty [Map] otherwise. - */ -@kotlin.internal.InlineOnly -public inline fun Map?.orEmpty() : Map = this ?: emptyMap() - -/** - * Checks if the map contains the given key. This method allows to use the `x in map` syntax for checking - * whether an object is contained in the map. - */ -@kotlin.internal.InlineOnly -public inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map.contains(key: K) : Boolean = containsKey(key) - -/** - * Allows to use the index operator for storing values in a mutable map. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableMap.set(key: K, value: V): Unit { - put(key, value) -} - -/** - * Returns the value corresponding to the given [key], or `null` if such a key is not present in the map. - */ -@kotlin.internal.InlineOnly -public inline operator fun <@kotlin.internal.OnlyInputTypes K, V> Map.get(key: K): V? - = @Suppress("UNCHECKED_CAST") (this as Map).get(key) - -/** - * Returns `true` if the map contains the specified [key]. - * - * Allows to overcome type-safety restriction of `containsKey` that requires to pass a key of type `K`. - */ -@kotlin.internal.InlineOnly -public inline fun <@kotlin.internal.OnlyInputTypes K> Map.containsKey(key: K): Boolean - = @Suppress("UNCHECKED_CAST") (this as Map).containsKey(key) - -/** - * Returns `true` if the map maps one or more keys to the specified [value]. - * - * Allows to overcome type-safety restriction of `containsValue` that requires to pass a value of type `V`. - */ -@kotlin.internal.InlineOnly -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -public inline fun Map.containsValue(value: V): Boolean = this.containsValue(value) - - -/** - * Removes the specified key and its corresponding value from this map. - * - * @return the previous value associated with the key, or `null` if the key was not present in the map. - - * Allows to overcome type-safety restriction of `remove` that requires to pass a key of type `K`. - */ -@kotlin.internal.InlineOnly -public inline fun <@kotlin.internal.OnlyInputTypes K, V> MutableMap.remove(key: K): V? - = @Suppress("UNCHECKED_CAST") (this as MutableMap).remove(key) - -/** - * Returns the key component of the map entry. - * - * This method allows to use destructuring declarations when working with maps, for example: - * ``` - * for ((key, value) in map) { - * // do something with the key and the value - * } - * ``` - */ -@kotlin.internal.InlineOnly -public inline operator fun Map.Entry.component1(): K = key - -/** - * Returns the value component of the map entry. - * This method allows to use destructuring declarations when working with maps, for example: - * ``` - * for ((key, value) in map) { - * // do something with the key and the value - * } - * ``` - */ -@kotlin.internal.InlineOnly -public inline operator fun Map.Entry.component2(): V = value - -/** - * Converts entry to [Pair] with key being first component and value being second. - */ -@kotlin.internal.InlineOnly -public inline fun Map.Entry.toPair(): Pair = Pair(key, value) - -/** - * Returns the value for the given key, or the result of the [defaultValue] function if there was no entry for the given key. - * - * @sample samples.collections.Maps.Usage.getOrElse - */ -public inline fun Map.getOrElse(key: K, defaultValue: () -> V): V = get(key) ?: defaultValue() - - -internal inline fun Map.getOrElseNullable(key: K, defaultValue: () -> V): V { - val value = get(key) - if (value == null && !containsKey(key)) { - return defaultValue() - } else { - @Suppress("UNCHECKED_CAST") - return value as V - } -} - -/** - * Returns the value for the given [key] or throws an exception if there is no such key in the map. - * - * If the map was created by [withDefault], resorts to its `defaultValue` provider function - * instead of throwing an exception. - * - * @throws NoSuchElementException when the map doesn't contain a value for the specified key and - * no implicit default value was provided for that map. - */ -@SinceKotlin("1.1") -public fun Map.getValue(key: K): V = getOrImplicitDefault(key) - -/** - * Returns the value for the given key. If the key is not found in the map, calls the [defaultValue] function, - * puts its result into the map under the given key and returns it. - * - * @sample samples.collections.Maps.Usage.getOrPut - */ -public inline fun MutableMap.getOrPut(key: K, defaultValue: () -> V): V { - val value = get(key) - return if (value == null) { - val answer = defaultValue() - put(key, answer) - answer - } else { - value - } -} - -/** - * Returns an [Iterator] over the entries in the [Map]. - * - * @sample samples.collections.Maps.Usage.forOverEntries - */ -@kotlin.internal.InlineOnly -public inline operator fun Map.iterator(): Iterator> = entries.iterator() - -/** - * Returns a [MutableIterator] over the mutable entries in the [MutableMap]. - * - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableMap.iterator(): MutableIterator> = entries.iterator() - -/** - * Populates the given [destination] map with entries having the keys of this map and the values obtained - * by applying the [transform] function to each entry in this [Map]. - */ -@kotlin.internal.InlineOnly -public inline fun > Map.mapValuesTo(destination: M, transform: (Map.Entry) -> R): M { - return entries.associateByTo(destination, { it.key }, transform) -} - -/** - * Populates the given [destination] map with entries having the keys obtained - * by applying the [transform] function to each entry in this [Map] and the values of this map. - * - * In case if any two entries are mapped to the equal keys, the value of the latter one will overwrite - * the value associated with the former one. - */ -@kotlin.internal.InlineOnly -public inline fun > Map.mapKeysTo(destination: M, transform: (Map.Entry) -> R): M { - return entries.associateByTo(destination, transform, { it.value }) -} - -/** - * Puts all the given [pairs] into this [MutableMap] with the first component in the pair being the key and the second the value. - */ -public fun MutableMap.putAll(pairs: Array>): Unit { - for ((key, value) in pairs) { - put(key, value) - } -} - -/** - * Puts all the elements of the given collection into this [MutableMap] with the first component in the pair being the key and the second the value. - */ -public fun MutableMap.putAll(pairs: Iterable>): Unit { - for ((key, value) in pairs) { - put(key, value) - } -} - -/** - * Puts all the elements of the given sequence into this [MutableMap] with the first component in the pair being the key and the second the value. - */ -public fun MutableMap.putAll(pairs: Sequence>): Unit { - for ((key, value) in pairs) { - put(key, value) - } -} - -/** - * Returns a new map with entries having the keys of this map and the values obtained by applying the [transform] - * function to each entry in this [Map]. - * - * The returned map preserves the entry iteration order of the original map. - * - * @sample samples.collections.Maps.Transforms.mapValues - */ -public inline fun Map.mapValues(transform: (Map.Entry) -> R): Map { - @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") - return mapValuesTo(HashMap( - mapCapacity(size)), - transform).optimizeReadOnlyMap() -} - -/** - * Returns a new Map with entries having the keys obtained by applying the [transform] function to each entry in this - * [Map] and the values of this map. - * - * In case if any two entries are mapped to the equal keys, the value of the latter one will overwrite - * the value associated with the former one. - * - * The returned map preserves the entry iteration order of the original map. - * - * @sample samples.collections.Maps.Transforms.mapKeys - */ -public inline fun Map.mapKeys(transform: (Map.Entry) -> R): Map { - @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") - return mapKeysTo(HashMap( - mapCapacity(size)), - transform).optimizeReadOnlyMap() -} - -/** - * Returns a map containing all key-value pairs with keys matching the given [predicate]. - * - * The returned map preserves the entry iteration order of the original map. - */ -public inline fun Map.filterKeys(predicate: (K) -> Boolean): Map { - val result = HashMap() - for (entry in this) { - if (predicate(entry.key)) { - result.put(entry.key, entry.value) - } - } - return result -} - -/** - * Returns a map containing all key-value pairs with values matching the given [predicate]. - * - * The returned map preserves the entry iteration order of the original map. - */ -public inline fun Map.filterValues(predicate: (V) -> Boolean): Map { - val result = HashMap() - for (entry in this) { - if (predicate(entry.value)) { - result.put(entry.key, entry.value) - } - } - return result -} - - -/** - * Appends all entries matching the given [predicate] into the mutable map given as [destination] parameter. - * - * @return the destination map. - */ -public inline fun > Map.filterTo(destination: M, predicate: (Map.Entry) -> Boolean): M { - for (element in this) { - if (predicate(element)) { - destination.put(element.key, element.value) - } - } - return destination -} - -/** - * Returns a new map containing all key-value pairs matching the given [predicate]. - * - * The returned map preserves the entry iteration order of the original map. - */ -public inline fun Map.filter(predicate: (Map.Entry) -> Boolean): Map { - return filterTo(HashMap(), predicate) -} - -/** - * Appends all entries not matching the given [predicate] into the given [destination]. - * - * @return the destination map. - */ -public inline fun > Map.filterNotTo(destination: M, predicate: (Map.Entry) -> Boolean): M { - for (element in this) { - if (!predicate(element)) { - destination.put(element.key, element.value) - } - } - return destination -} - -/** - * Returns a new map containing all key-value pairs not matching the given [predicate]. - * - * The returned map preserves the entry iteration order of the original map. - */ -public inline fun Map.filterNot(predicate: (Map.Entry) -> Boolean): Map { - return filterNotTo(HashMap(), predicate) -} - -/** - * Returns a new map containing all key-value pairs from the given collection of pairs. - * - * The returned map preserves the entry iteration order of the original collection. - */ -public fun Iterable>.toMap(): Map { - if (this is Collection) { - return when (size) { - 0 -> emptyMap() - 1 -> mapOf(if (this is List) this[0] else iterator().next()) - else -> toMap(HashMap(mapCapacity(size))) - } - } - return toMap(HashMap()).optimizeReadOnlyMap() -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs from the given collection of pairs. - */ -public fun > Iterable>.toMap(destination: M): M - = destination.apply { putAll(this@toMap) } - -/** - * Returns a new map containing all key-value pairs from the given array of pairs. - * - * The returned map preserves the entry iteration order of the original array. - */ -public fun Array>.toMap(): Map = when(size) { - 0 -> emptyMap() - 1 -> mapOf(this[0]) - else -> toMap(HashMap(mapCapacity(size))) -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs from the given array of pairs. - */ -public fun > Array>.toMap(destination: M): M - = destination.apply { putAll(this@toMap) } - -/** - * Returns a new map containing all key-value pairs from the given sequence of pairs. - * - * The returned map preserves the entry iteration order of the original sequence. - */ -public fun Sequence>.toMap(): Map = toMap(HashMap()).optimizeReadOnlyMap() - -/** - * Populates and returns the [destination] mutable map with key-value pairs from the given sequence of pairs. - */ -public fun > Sequence>.toMap(destination: M): M - = destination.apply { putAll(this@toMap) } - -/** - * Returns a new read-only map containing all key-value pairs from the original map. - * - * The returned map preserves the entry iteration order of the original map. - */ -@SinceKotlin("1.1") -public fun Map.toMap(): Map = when (size) { - 0 -> emptyMap() -// 1 -> toSingletonMap() - else -> toMutableMap() -} - -/** - * Returns a new mutable map containing all key-value pairs from the original map. - * - * The returned map preserves the entry iteration order of the original map. - */ -@SinceKotlin("1.1") -public fun Map.toMutableMap(): MutableMap = HashMap(this) - -/** - * Populates and returns the [destination] mutable map with key-value pairs from the given map. - */ -public fun > Map.toMap(destination: M): M - = destination.apply { putAll(this@toMap) } - -/** - * Creates a new read-only map by replacing or adding an entry to this map from a given key-value [pair]. - * - * The returned map preserves the entry iteration order of the original map. - * The [pair] is iterated in the end if it has a unique key. - */ -public operator fun Map.plus(pair: Pair): Map - = if (this.isEmpty()) mapOf(pair) else HashMap(this).apply { put(pair.first, pair.second) } - -/** - * Creates a new read-only map by replacing or adding entries to this map from a given collection of key-value [pairs]. - * - * The returned map preserves the entry iteration order of the original map. - * Those [pairs] with unique keys are iterated in the end in the order of [pairs] collection. - */ -public operator fun Map.plus(pairs: Iterable>): Map - = if (this.isEmpty()) pairs.toMap() else HashMap(this).apply { putAll(pairs) } - -/** - * Creates a new read-only map by replacing or adding entries to this map from a given array of key-value [pairs]. - * - * The returned map preserves the entry iteration order of the original map. - * Those [pairs] with unique keys are iterated in the end in the order of [pairs] array. - */ -public operator fun Map.plus(pairs: Array>): Map - = if (this.isEmpty()) pairs.toMap() else HashMap(this).apply { putAll(pairs) } - -/** - * Creates a new read-only map by replacing or adding entries to this map from a given sequence of key-value [pairs]. - * - * The returned map preserves the entry iteration order of the original map. - * Those [pairs] with unique keys are iterated in the end in the order of [pairs] sequence. - */ -public operator fun Map.plus(pairs: Sequence>): Map - = HashMap(this).apply { putAll(pairs) }.optimizeReadOnlyMap() - -/** - * Creates a new read-only map by replacing or adding entries to this map from another [map]. - * - * The returned map preserves the entry iteration order of the original map. - * Those entries of another [map] that are missing in this map are iterated in the end in the order of that [map]. - */ -public operator fun Map.plus(map: Map): Map - = HashMap(this).apply { putAll(map) } - -/** - * Appends or replaces the given [pair] in this mutable map. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableMap.plusAssign(pair: Pair) { - put(pair.first, pair.second) -} - -/** - * Appends or replaces all pairs from the given collection of [pairs] in this mutable map. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableMap.plusAssign(pairs: Iterable>) { - putAll(pairs) -} - -/** - * Appends or replaces all pairs from the given array of [pairs] in this mutable map. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableMap.plusAssign(pairs: Array>) { - putAll(pairs) -} - -/** - * Appends or replaces all pairs from the given sequence of [pairs] in this mutable map. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableMap.plusAssign(pairs: Sequence>) { - putAll(pairs) -} - -/** - * Appends or replaces all entries from the given [map] in this mutable map. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableMap.plusAssign(map: Map) { - putAll(map) -} - -/** - * Returns a map containing all entries of the original map except the entry with the given [key]. - * - * The returned map preserves the entry iteration order of the original map. - */ -@SinceKotlin("1.1") -public operator fun Map.minus(key: K): Map - = this.toMutableMap().apply { minusAssign(key) }.optimizeReadOnlyMap() - -/** - * Returns a map containing all entries of the original map except those entries - * the keys of which are contained in the given [keys] collection. - * - * The returned map preserves the entry iteration order of the original map. - */ -@SinceKotlin("1.1") -public operator fun Map.minus(keys: Iterable): Map - = this.toMutableMap().apply { minusAssign(keys) }.optimizeReadOnlyMap() - -/** - * Returns a map containing all entries of the original map except those entries - * the keys of which are contained in the given [keys] array. - * - * The returned map preserves the entry iteration order of the original map. - */ -@SinceKotlin("1.1") -public operator fun Map.minus(keys: Array): Map - = this.toMutableMap().apply { minusAssign(keys) }.optimizeReadOnlyMap() - -/** - * Returns a map containing all entries of the original map except those entries - * the keys of which are contained in the given [keys] sequence. - * - * The returned map preserves the entry iteration order of the original map. - */ -@SinceKotlin("1.1") -public operator fun Map.minus(keys: Sequence): Map - = this.toMutableMap().apply { minusAssign(keys) }.optimizeReadOnlyMap() - -/** - * Removes the entry with the given [key] from this mutable map. - */ -@SinceKotlin("1.1") -@kotlin.internal.InlineOnly -public inline operator fun MutableMap.minusAssign(key: K) { - remove(key) -} - -/** - * Removes all entries the keys of which are contained in the given [keys] collection from this mutable map. - */ -@SinceKotlin("1.1") -@kotlin.internal.InlineOnly -public inline operator fun MutableMap.minusAssign(keys: Iterable) { - this.keys.removeAll(keys) -} - -/** - * Removes all entries the keys of which are contained in the given [keys] array from this mutable map. - */ -@SinceKotlin("1.1") -@kotlin.internal.InlineOnly -public inline operator fun MutableMap.minusAssign(keys: Array) { - this.keys.removeAll(keys) -} - -/** - * Removes all entries from the keys of which are contained in the given [keys] sequence from this mutable map. - */ -@SinceKotlin("1.1") -@kotlin.internal.InlineOnly -public inline operator fun MutableMap.minusAssign(keys: Sequence) { - this.keys.removeAll(keys) -} - -@kotlin.internal.InlineExposed -internal fun Map.optimizeReadOnlyMap() = when (size) { - 0 -> emptyMap() -// 1 -> toSingletonMapOrSelf() - else -> this -} - // creates a singleton copy of map, if there is specialization available in target platform, otherwise returns itself -// internal inline fun Map.toSingletonMapOrSelf(): Map = toSingletonMap() +internal inline actual fun Map.toSingletonMapOrSelf(): Map = toSingletonMap() // creates a singleton copy of map -//internal fun Map.toSingletonMap(): Map -// = with (entries.iterator().next()) { java.util.Collections.singletonMap(key, value) } - -// This is from generated _Maps.kt. -/** - * Returns a [List] containing all key-value pairs. - */ -public fun Map.toList(): List> { - if (size == 0) - return emptyList() - val iterator = entries.iterator() - if (!iterator.hasNext()) - return emptyList() - val first = iterator.next() - if (!iterator.hasNext()) - return listOf(first.toPair()) - val result = ArrayList>(size) - result.add(first.toPair()) - do { - result.add(iterator.next().toPair()) - } while (iterator.hasNext()) - return result -} - -/** - * Returns a single list of all elements yielded from results of [transform] function being invoked on each entry of original map. - */ -public inline fun Map.flatMap(transform: (Map.Entry) -> Iterable): List { - return flatMapTo(ArrayList(), transform) -} - -/** - * Appends all elements yielded from results of [transform] function being invoked on each entry of original map, to the given [destination]. - */ -public inline fun > Map.flatMapTo(destination: C, transform: (Map.Entry) -> Iterable): C { - for (element in this) { - val list = transform(element) - destination.addAll(list) - } - return destination -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each entry in the original map. - */ -public inline fun Map.map(transform: (Map.Entry) -> R): List { - return mapTo(ArrayList(size), transform) -} - -/** - * Returns a list containing only the non-null results of applying the given [transform] function - * to each entry in the original map. - */ -public inline fun Map.mapNotNull(transform: (Map.Entry) -> R?): List { - return mapNotNullTo(ArrayList(), transform) -} - -/** - * Applies the given [transform] function to each entry in the original map - * and appends only the non-null results to the given [destination]. - */ -public inline fun > Map.mapNotNullTo(destination: C, transform: (Map.Entry) -> R?): C { - forEach { element -> transform(element)?.let { destination.add(it) } } - return destination -} - -/** - * Applies the given [transform] function to each entry of the original map - * and appends the results to the given [destination]. - */ -public inline fun > Map.mapTo(destination: C, transform: (Map.Entry) -> R): C { - for (item in this) - destination.add(transform(item)) - return destination -} - -/** - * Returns `true` if all entries match the given [predicate]. - */ -public inline fun Map.all(predicate: (Map.Entry) -> Boolean): Boolean { - for (element in this) if (!predicate(element)) return false - return true -} - -/** - * Returns `true` if map has at least one entry. - */ -public fun Map.any(): Boolean { - for (element in this) return true - return false -} - -/** - * Returns `true` if at least one entry matches the given [predicate]. - */ -public inline fun Map.any(predicate: (Map.Entry) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return true - return false -} - -/** - * Returns the number of entries in this map. - */ -@kotlin.internal.InlineOnly -public inline fun Map.count(): Int { - return size -} - -/** - * Returns the number of entries matching the given [predicate]. - */ -public inline fun Map.count(predicate: (Map.Entry) -> Boolean): Int { - var count = 0 - for (element in this) if (predicate(element)) count++ - return count -} - -/** - * Performs the given [action] on each entry. - */ -@kotlin.internal.HidesMembers -public inline fun Map.forEach(action: (Map.Entry) -> Unit): Unit { - for (element in this) action(element) -} - -/** - * Returns the first entry yielding the largest value of the given function or `null` if there are no entries. - */ -@kotlin.internal.InlineOnly -public inline fun > Map.maxBy(selector: (Map.Entry) -> R): Map.Entry? { - return entries.maxBy(selector) -} - -/** - * Returns the first entry having the largest value according to the provided [comparator] or `null` if there are no entries. - */ -@kotlin.internal.InlineOnly -public inline fun Map.maxWith(comparator: Comparator>): Map.Entry? { - return entries.maxWith(comparator) -} - -/** - * Returns the first entry yielding the smallest value of the given function or `null` if there are no entries. - */ -public inline fun > Map.minBy(selector: (Map.Entry) -> R): Map.Entry? { - return entries.minBy(selector) -} - -/** - * Returns the first entry having the smallest value according to the provided [comparator] or `null` if there are no entries. - */ -public fun Map.minWith(comparator: Comparator>): Map.Entry? { - return entries.minWith(comparator) -} - -/** - * Returns `true` if the map has no entries. - */ -public fun Map.none(): Boolean { - for (element in this) return false - return true -} - -/** - * Returns `true` if no entries match the given [predicate]. - */ -public inline fun Map.none(predicate: (Map.Entry) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return false - return true -} - -/** - * Performs the given [action] on each entry and returns the map itself afterwards. - */ -@SinceKotlin("1.1") -public inline fun > M.onEach(action: (Map.Entry) -> Unit): M { - return apply { for (element in this) action(element) } -} - -/** - * Creates an [Iterable] instance that wraps the original map returning its entries when being iterated. - */ -@kotlin.internal.InlineOnly -public inline fun Map.asIterable(): Iterable> { - return entries -} - -/** - * Creates a [Sequence] instance that wraps the original map returning its entries when being iterated. - */ -public fun Map.asSequence(): Sequence> { - return entries.asSequence() -} - +internal actual fun Map.toSingletonMap(): Map + = this.toMutableMap() // TODO diff --git a/runtime/src/main/kotlin/kotlin/collections/MutableCollections.kt b/runtime/src/main/kotlin/kotlin/collections/MutableCollections.kt index f306264eb96..dc44fed034e 100644 --- a/runtime/src/main/kotlin/kotlin/collections/MutableCollections.kt +++ b/runtime/src/main/kotlin/kotlin/collections/MutableCollections.kt @@ -18,268 +18,15 @@ package kotlin.collections import kotlin.comparisons.* -/** - * Removes a single instance of the specified element from this - * collection, if it is present. - * - * Allows to overcome type-safety restriction of `remove` that requires to pass an element of type `E`. - * - * @return `true` if the element has been successfully removed; `false` if it was not present in the collection. - */ -@kotlin.internal.InlineOnly -public inline fun <@kotlin.internal.OnlyInputTypes T> MutableCollection.remove(element: T): Boolean - = @Suppress("UNCHECKED_CAST") (this as MutableCollection).remove(element) - -/** - * Removes all of this collection's elements that are also contained in the specified collection. - - * Allows to overcome type-safety restriction of `removeAll` that requires to pass a collection of type `Collection`. - * - * @return `true` if any of the specified elements was removed from the collection, `false` if the collection was not modified. - */ -@kotlin.internal.InlineOnly -public inline fun <@kotlin.internal.OnlyInputTypes T> MutableCollection.removeAll(elements: Collection): Boolean - = @Suppress("UNCHECKED_CAST") (this as MutableCollection).removeAll(elements) - -/** - * Retains only the elements in this collection that are contained in the specified collection. - * - * Allows to overcome type-safety restriction of `retailAll` that requires to pass a collection of type `Collection`. - * - * @return `true` if any element was removed from the collection, `false` if the collection was not modified. - */ -@kotlin.internal.InlineOnly -public inline fun <@kotlin.internal.OnlyInputTypes T> MutableCollection.retainAll(elements: Collection): Boolean - = @Suppress("UNCHECKED_CAST") (this as MutableCollection).retainAll(elements) - -/** - * Removes the element at the specified [index] from this list. - * In Kotlin one should use the [MutableList.removeAt] function instead. - */ -@Deprecated("Use removeAt(index) instead.", ReplaceWith("removeAt(index)"), level = DeprecationLevel.ERROR) -@kotlin.internal.InlineOnly -public inline fun MutableList.remove(index: Int): T = removeAt(index) - -/** - * Adds the specified [element] to this mutable collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableCollection.plusAssign(element: T) { - this.add(element) -} - -/** - * Adds all elements of the given [elements] collection to this mutable collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableCollection.plusAssign(elements: Iterable) { - this.addAll(elements) -} - -/** - * Adds all elements of the given [elements] array to this mutable collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableCollection.plusAssign(elements: Array) { - this.addAll(elements) -} - -/** - * Adds all elements of the given [elements] sequence to this mutable collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableCollection.plusAssign(elements: Sequence) { - this.addAll(elements) -} - -/** - * Removes a single instance of the specified [element] from this mutable collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableCollection.minusAssign(element: T) { - this.remove(element) -} - -/** - * Removes all elements contained in the given [elements] collection from this mutable collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableCollection.minusAssign(elements: Iterable) { - this.removeAll(elements) -} - -/** - * Removes all elements contained in the given [elements] array from this mutable collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableCollection.minusAssign(elements: Array) { - this.removeAll(elements) -} - -/** - * Removes all elements contained in the given [elements] sequence from this mutable collection. - */ -@kotlin.internal.InlineOnly -public inline operator fun MutableCollection.minusAssign(elements: Sequence) { - this.removeAll(elements) -} - -/** - * Adds all elements of the given [elements] collection to this [MutableCollection]. - */ -public fun MutableCollection.addAll(elements: Iterable): Boolean { - when (elements) { - is Collection -> return addAll(elements) - else -> { - var result: Boolean = false - for (item in elements) - if (add(item)) result = true - return result - } - } -} - -/** - * Adds all elements of the given [elements] sequence to this [MutableCollection]. - */ -public fun MutableCollection.addAll(elements: Sequence): Boolean { - var result: Boolean = false - for (item in elements) { - if (add(item)) result = true - } - return result -} - -/** - * Adds all elements of the given [elements] array to this [MutableCollection]. - */ -public fun MutableCollection.addAll(elements: Array): Boolean { - return addAll(elements.asList()) -} - -/** - * Removes all elements from this [MutableIterable] that match the given [predicate]. - */ -public fun MutableIterable.removeAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, true) - -/** - * Retains only elements of this [MutableIterable] that match the given [predicate]. - */ -public fun MutableIterable.retainAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, false) - -private fun MutableIterable.filterInPlace(predicate: (T) -> Boolean, predicateResultToRemove: Boolean): Boolean { - var result = false - with (iterator()) { - while (hasNext()) - if (predicate(next()) == predicateResultToRemove) { - remove() - result = true - } - } - return result -} - -/** - * Removes all elements from this [MutableList] that match the given [predicate]. - */ -public fun MutableList.removeAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, true) - -/** - * Retains only elements of this [MutableList] that match the given [predicate]. - */ -public fun MutableList.retainAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, false) - -private fun MutableList.filterInPlace(predicate: (T) -> Boolean, predicateResultToRemove: Boolean): Boolean { - if (this !is RandomAccess) - return (this as MutableIterable).filterInPlace(predicate, predicateResultToRemove) - - var writeIndex: Int = 0 - for (readIndex in 0..lastIndex) { - val element = this[readIndex] - if (predicate(element) == predicateResultToRemove) - continue - - if (writeIndex != readIndex) - this[writeIndex] = element - - writeIndex++ - } - if (writeIndex < size) { - for (removeIndex in lastIndex downTo writeIndex) - removeAt(removeIndex) - - return true - } - else { - return false - } -} - -/** - * Removes all elements from this [MutableCollection] that are also contained in the given [elements] collection. - */ -public fun MutableCollection.removeAll(elements: Iterable): Boolean { - return removeAll(elements.convertToSetForSetOperationWith(this)) -} - -/** - * Removes all elements from this [MutableCollection] that are also contained in the given [elements] sequence. - */ -public fun MutableCollection.removeAll(elements: Sequence): Boolean { - val set = elements.toHashSet() - return set.isNotEmpty() && removeAll(set) -} - -/** - * Removes all elements from this [MutableCollection] that are also contained in the given [elements] array. - */ -public fun MutableCollection.removeAll(elements: Array): Boolean { - return elements.isNotEmpty() && removeAll(elements.toHashSet()) -} - -/** - * Retains only elements of this [MutableCollection] that are contained in the given [elements] collection. - */ -public fun MutableCollection.retainAll(elements: Iterable): Boolean { - return retainAll(elements.convertToSetForSetOperationWith(this)) -} - -/** - * Retains only elements of this [MutableCollection] that are contained in the given [elements] array. - */ -public fun MutableCollection.retainAll(elements: Array): Boolean { - if (elements.isNotEmpty()) - return retainAll(elements.toHashSet()) - else - return retainNothing() -} - -/** - * Retains only elements of this [MutableCollection] that are contained in the given [elements] sequence. - */ -public fun MutableCollection.retainAll(elements: Sequence): Boolean { - val set = elements.toHashSet() - if (set.isNotEmpty()) - return retainAll(set) - else - return retainNothing() -} - -private fun MutableCollection<*>.retainNothing(): Boolean { - val result = isNotEmpty() - clear() - return result -} - /** * Sorts elements in the list in-place according to their natural sort order. */ -public fun > MutableList.sort(): Unit = sortWith(Comparator { a: T, b: T -> a.compareTo(b) }) +public actual fun > MutableList.sort(): Unit = sortWith(Comparator { a: T, b: T -> a.compareTo(b) }) /** * Sorts elements in the list in-place according to the order specified with [comparator]. */ -public fun MutableList.sortWith(comparator: Comparator): Unit { +public actual fun MutableList.sortWith(comparator: Comparator): Unit { if (size > 1) { val it = listIterator() val sortedArray = @Suppress("TYPE_PARAMETER_AS_REIFIED") toTypedArray().apply { sortWith(comparator) } @@ -289,3 +36,51 @@ public fun MutableList.sortWith(comparator: Comparator): Unit { } } } +/** + * Provides a skeletal implementation of the [MutableMap] interface. + * + * The implementor is required to implement [entries] property, which should return mutable set of map entries, and [put] function. + * + * @param K the type of map keys. The map is invariant on its key type. + * @param V the type of map values. The map is invariant on its value type. + */ +@SinceKotlin("1.1") +actual abstract class AbstractMutableMap protected actual constructor() : AbstractMap(), MutableMap { + /** + * Associates the specified [value] with the specified [key] in the map. + * + * This method is redeclared as abstract, because it's not implemented in the base class, + * so it must be always overridden in the concrete mutable collection implementation. + * + * @return the previous value associated with the key, or `null` if the key was not present in the map. + */ + actual abstract override fun put(key: K, value: V): V? + + /** + * Returns a [Set] of all keys in this map. + */ + abstract override val keys: MutableSet + + /** + * Returns a [Collection] of all values in this map. + */ + abstract override val values: MutableCollection +} + +/** + * Provides a skeletal implementation of the [MutableSet] interface. + * + * @param E the type of elements contained in the set. The set is invariant on its element type. + */ +@SinceKotlin("1.1") +actual abstract class AbstractMutableSet protected actual constructor() : AbstractSet(), MutableSet { + /** + * Adds the specified element to the set. + * + * This method is redeclared as abstract, because it's not implemented in the base class, + * so it must be always overridden in the concrete mutable collection implementation. + * + * @return `true` if the element has been added, `false` if the element is already contained in the set. + */ + actual abstract override fun add(element: E): Boolean +} \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/collections/RandomAccess.kt b/runtime/src/main/kotlin/kotlin/collections/RandomAccess.kt index dc49997d308..a3ce1299f27 100644 --- a/runtime/src/main/kotlin/kotlin/collections/RandomAccess.kt +++ b/runtime/src/main/kotlin/kotlin/collections/RandomAccess.kt @@ -16,4 +16,5 @@ package kotlin.collections -public interface RandomAccess +// A marker interface indicating the fast indexed access support +public actual interface RandomAccess diff --git a/runtime/src/main/kotlin/kotlin/collections/ReversedViews.kt b/runtime/src/main/kotlin/kotlin/collections/ReversedViews.kt deleted file mode 100644 index 6e80ffc75c3..00000000000 --- a/runtime/src/main/kotlin/kotlin/collections/ReversedViews.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.collections - -private open class ReversedListReadOnly(private val delegate: List) : AbstractList() { - override val size: Int get() = delegate.size - override fun get(index: Int): T = delegate[reverseElementIndex(index)] - -} - -private class ReversedList(private val delegate: MutableList) : AbstractMutableList() { - override val size: Int get() = delegate.size - override fun get(index: Int): T = delegate[reverseElementIndex(index)] - - override fun clear() = delegate.clear() - override fun removeAt(index: Int): T = delegate.removeAt(reverseElementIndex(index)) - - override fun set(index: Int, element: T): T = delegate.set(reverseElementIndex(index), element) - override fun add(index: Int, element: T) { - delegate.add(reversePositionIndex(index), element) - } -} -private fun List<*>.reverseElementIndex(index: Int) = // TODO: Use AbstractList.checkElementIndex: run { AbstractList.checkElementIndex(index, size); lastIndex - index } - if (index in 0..size - 1) size - index - 1 else throw IndexOutOfBoundsException("Index $index should be in range [${0..size - 1}].") - -private fun List<*>.reversePositionIndex(index: Int) = - if (index in 0..size) size - index else throw IndexOutOfBoundsException("Index $index should be in range [${0..size}].") - - -/** - * Returns a reversed read-only view of the original List. - * All changes made in the original list will be reflected in the reversed one. - */ -public fun List.asReversed(): List = ReversedListReadOnly(this) - -/** - * Returns a reversed mutable view of the original mutable List. - * All changes made in the original list will be reflected in the reversed one and vice versa. - */ -public fun MutableList.asReversed(): MutableList = ReversedList(this) diff --git a/runtime/src/main/kotlin/kotlin/collections/Set.kt b/runtime/src/main/kotlin/kotlin/collections/Set.kt index c34331a8830..e6e2b279101 100644 --- a/runtime/src/main/kotlin/kotlin/collections/Set.kt +++ b/runtime/src/main/kotlin/kotlin/collections/Set.kt @@ -52,3 +52,9 @@ public interface MutableSet : Set, MutableCollection { override fun retainAll(elements: Collection): Boolean override fun clear(): Unit } + +// TODO: Add SingletonSet class +/** + * Returns an immutable set containing only the specified object [element]. + */ +public fun setOf(element: T): Set = hashSetOf(element) diff --git a/runtime/src/main/kotlin/kotlin/collections/Sets.kt b/runtime/src/main/kotlin/kotlin/collections/Sets.kt deleted file mode 100644 index 92cee016207..00000000000 --- a/runtime/src/main/kotlin/kotlin/collections/Sets.kt +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.collections - - -internal object EmptySet : Set, konan.internal.KonanSet { - override fun equals(other: Any?): Boolean = other is Set<*> && other.isEmpty() - override fun hashCode(): Int = 0 - override fun toString(): String = "[]" - - override val size: Int get() = 0 - override fun isEmpty(): Boolean = true - override fun contains(element: Nothing): Boolean = false - override fun getElement(element: Nothing): Nothing? = null - override fun containsAll(elements: Collection): Boolean = elements.isEmpty() - - override fun iterator(): Iterator = EmptyIterator - - private fun readResolve(): Any = EmptySet -} - - -/** Returns an empty read-only set. The returned set is serializable (JVM). */ -public fun emptySet(): Set = EmptySet -/** - * Returns a new read-only set with the given elements. - * Elements of the set are iterated in the order they were specified. - */ -public fun setOf(vararg elements: T): Set = if (elements.size > 0) elements.toSet() else emptySet() - -/** Returns an empty read-only set. */ -@kotlin.internal.InlineOnly -public inline fun setOf(): Set = emptySet() - -/** - * Returns a new [MutableSet] with the given elements. - * Elements of the set are iterated in the order they were specified. - */ -public fun mutableSetOf(vararg elements: T): MutableSet = elements.toCollection(HashSet(mapCapacity(elements.size))) - -/** Returns a new [HashSet] with the given elements. */ -public fun hashSetOf(vararg elements: T): HashSet = elements.toCollection(HashSet(mapCapacity(elements.size))) - -/** - * Returns a new [LinkedHashSet] with the given elements. - * Elements of the set are iterated in the order they were specified. - */ -public fun linkedSetOf(vararg elements: T): LinkedHashSet = elements.toCollection(LinkedHashSet(mapCapacity(elements.size))) - -/** Returns this Set if it's not `null` and the empty set otherwise. */ -@kotlin.internal.InlineOnly -public inline fun Set?.orEmpty(): Set = this ?: emptySet() - -// TODO: Add SingletonSet class -/** - * Returns an immutable set containing only the specified object [element]. - */ -public fun setOf(element: T): Set = hashSetOf(element) - - -/** - * Returns a new [SortedSet] with the given elements. - */ -// public fun sortedSetOf(vararg elements: T): TreeSet = elements.toCollection(TreeSet()) - -/** - * Returns a new [SortedSet] with the given [comparator] and elements. - */ -//public fun sortedSetOf(comparator: Comparator, vararg elements: T): TreeSet = elements.toCollection(TreeSet(comparator)) - - -internal fun Set.optimizeReadOnlySet() = when (size) { - 0 -> emptySet() - 1 -> setOf(iterator().next()) - else -> this -} - -/** - * Returns a set containing all elements of the original set except the given [element]. - * - * The returned set preserves the element iteration order of the original set. - */ -public operator fun Set.minus(element: T): Set { - val result = LinkedHashSet(mapCapacity(size)) - var removed = false - return this.filterTo(result) { if (!removed && it == element) { removed = true; false } else true } -} - -/** - * Returns a set containing all elements of the original set except the elements contained in the given [elements] array. - * - * The returned set preserves the element iteration order of the original set. - */ -public operator fun Set.minus(elements: Array): Set { - val result = LinkedHashSet(this) - result.removeAll(elements) - return result -} - -/** - * Returns a set containing all elements of the original set except the elements contained in the given [elements] collection. - * - * The returned set preserves the element iteration order of the original set. - */ -public operator fun Set.minus(elements: Iterable): Set { - val other = elements.convertToSetForSetOperationWith(this) - if (other.isEmpty()) - return this.toSet() - if (other is Set) - return this.filterNotTo(LinkedHashSet()) { it in other } - val result = LinkedHashSet(this) - result.removeAll(other) - return result -} - -/** - * Returns a set containing all elements of the original set except the elements contained in the given [elements] sequence. - * - * The returned set preserves the element iteration order of the original set. - */ -public operator fun Set.minus(elements: Sequence): Set { - val result = LinkedHashSet(this) - result.removeAll(elements) - return result -} - -/** - * Returns a set containing all elements of the original set except the given [element]. - * - * The returned set preserves the element iteration order of the original set. - */ -@kotlin.internal.InlineOnly -public inline fun Set.minusElement(element: T): Set { - return minus(element) -} - -/** - * Returns a set containing all elements of the original set and then the given [element] if it isn't already in this set. - * - * The returned set preserves the element iteration order of the original set. - */ -public operator fun Set.plus(element: T): Set { - val result = LinkedHashSet(mapCapacity(size + 1)) - result.addAll(this) - result.add(element) - return result -} - -/** - * Returns a set containing all elements of the original set and the given [elements] array, - * which aren't already in this set. - * - * The returned set preserves the element iteration order of the original set. - */ -public operator fun Set.plus(elements: Array): Set { - val result = LinkedHashSet(mapCapacity(this.size + elements.size)) - result.addAll(this) - result.addAll(elements) - return result -} - -/** - * Returns a set containing all elements of the original set and the given [elements] collection, - * which aren't already in this set. - * The returned set preserves the element iteration order of the original set. - */ -public operator fun Set.plus(elements: Iterable): Set { - val result = LinkedHashSet(mapCapacity(elements.collectionSizeOrNull()?.let { this.size + it } ?: this.size * 2)) - result.addAll(this) - result.addAll(elements) - return result -} - -/** - * Returns a set containing all elements of the original set and the given [elements] sequence, - * which aren't already in this set. - * - * The returned set preserves the element iteration order of the original set. - */ -public operator fun Set.plus(elements: Sequence): Set { - val result = LinkedHashSet(mapCapacity(this.size * 2)) - result.addAll(this) - result.addAll(elements) - return result -} - -/** - * Returns a set containing all elements of the original set and then the given [element] if it isn't already in this set. - * - * The returned set preserves the element iteration order of the original set. - */ -@kotlin.internal.InlineOnly -public inline fun Set.plusElement(element: T): Set { - return plus(element) -} - diff --git a/runtime/src/main/kotlin/kotlin/collections/SlidingWindow.kt b/runtime/src/main/kotlin/kotlin/collections/SlidingWindow.kt deleted file mode 100644 index fc29541c35d..00000000000 --- a/runtime/src/main/kotlin/kotlin/collections/SlidingWindow.kt +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.collections - -import kotlin.coroutines.experimental.buildIterator - -internal fun checkWindowSizeStep(size: Int, step: Int) { - require(size > 0 && step > 0) { - if (size != step) - "Both size $size and step $step must be greater than zero." - else - "size $size must be greater than zero." - } -} - -internal fun Sequence.windowedSequence(size: Int, step: Int, partialWindows: Boolean, reuseBuffer: Boolean): Sequence> { - checkWindowSizeStep(size, step) - return Sequence { windowedIterator(iterator(), size, step, partialWindows, reuseBuffer) } -} - -internal fun windowedIterator(iterator: Iterator, size: Int, step: Int, partialWindows: Boolean, reuseBuffer: Boolean): Iterator> { - if (!iterator.hasNext()) return EmptyIterator - return buildIterator> { - val gap = step - size - if (gap >= 0) { - var buffer = ArrayList(size) - var skip = 0 - for (e in iterator) { - if (skip > 0) { skip -= 1; continue } - buffer.add(e) - if (buffer.size == size) { - yield(buffer) - if (reuseBuffer) buffer.clear() else buffer = ArrayList(size) - skip = gap - } - } - if (buffer.isNotEmpty()) { - if (partialWindows || buffer.size == size) yield(buffer) - } - } else { - val buffer = RingBuffer(size) - for (e in iterator) { - buffer.add(e) - if (buffer.isFull()) { - yield(if (reuseBuffer) buffer else ArrayList(buffer)) - buffer.removeFirst(step) - } - } - if (partialWindows) { - while (buffer.size > step) { - yield(if (reuseBuffer) buffer else ArrayList(buffer)) - buffer.removeFirst(step) - } - if (buffer.isNotEmpty()) yield(buffer) - } - } - } -} - -internal class MovingSubList(private val list: List) : AbstractList(), RandomAccess { - private var fromIndex: Int = 0 - private var _size: Int = 0 - - fun move(fromIndex: Int, toIndex: Int) { - checkRangeIndexes(fromIndex, toIndex, list.size) - this.fromIndex = fromIndex - this._size = toIndex - fromIndex - } - - override fun get(index: Int): E { - checkElementIndex(index, _size) - - return list[fromIndex + index] - } - - override val size: Int get() = _size -} - - -/** - * Provides ring buffer implementation. - * - * Buffer overflow is not allowed so [add] doesn't overwrite tail but raises an exception. - */ -private class RingBuffer(val capacity: Int): AbstractList(), RandomAccess { - init { - require(capacity >= 0) { "ring buffer capacity should not be negative but it is $capacity" } - } - - private val buffer = arrayOfNulls(capacity) - private var startIndex: Int = 0 - - override var size: Int = 0 - private set - - override fun get(index: Int): T { - checkElementIndex(index, size) - @Suppress("UNCHECKED_CAST") - return buffer[startIndex.forward(index)] as T - } - - fun isFull() = size == capacity - - override fun iterator(): Iterator = object : AbstractIterator() { - private var count = size - private var index = startIndex - - override fun computeNext() { - if (count == 0) { - done() - } else { - @Suppress("UNCHECKED_CAST") - setNext(buffer[index] as T) - index = index.forward(1) - count-- - } - } - } - - @Suppress("UNCHECKED_CAST") - override fun toArray(array: Array): Array { - val result: Array = - if (array.size < this.size) array.copyOf(this.size) else array as Array - - val size = this.size - - var widx = 0 - var idx = startIndex - - while (widx < size && idx < capacity) { - result[widx] = buffer[idx] as T - widx++ - idx++ - } - - idx = 0 - while (widx < size) { - result[widx] = buffer[idx] as T - widx++ - idx++ - } - if (result.size > this.size) result[this.size] = null - - return result as Array - } - - override fun toArray(): Array { - return toArray(arrayOfNulls(size)) - } - - /** - * Add [element] to the buffer or fail with [IllegalStateException] if no free space available in the buffer - */ - fun add(element: T) { - if (isFull()) { - throw IllegalStateException("ring buffer is full") - } - - buffer[startIndex.forward(size)] = element - size++ - } - - /** - * Removes [n] first elements from the buffer or fails with [IllegalArgumentException] if not enough elements in the buffer to remove - */ - fun removeFirst(n: Int) { - require(n >= 0) { "n shouldn't be negative but it is $n" } - require(n <= size) { "n shouldn't be greater than the buffer size: n = $n, size = $size" } - - if (n > 0) { - val start = startIndex - val end = start.forward(n) - - if (start > end) { - buffer.fill(null, start, capacity) - buffer.fill(null, 0, end) - } else { - buffer.fill(null, start, end) - } - - startIndex = end - size -= n - } - } - - - @Suppress("NOTHING_TO_INLINE") - private inline fun Int.forward(n: Int): Int = (this + n) % capacity - - // TODO: replace with Array.fill from stdlib when available in common - private fun Array.fill(element: T, fromIndex: Int = 0, toIndex: Int = size): Unit { - for (idx in fromIndex .. toIndex-1) { - this[idx] = element - } - } -} \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/comparisons/Comparisons.kt b/runtime/src/main/kotlin/kotlin/comparisons/Comparisons.kt index 81502baa469..8c00b38f8c6 100644 --- a/runtime/src/main/kotlin/kotlin/comparisons/Comparisons.kt +++ b/runtime/src/main/kotlin/kotlin/comparisons/Comparisons.kt @@ -16,318 +16,14 @@ package kotlin.comparisons -interface Comparator { - fun compare(a: T, b: T): Int -} - -fun Comparator(function: (a: T, b: T) -> Int): Comparator { - return object: Comparator { - override fun compare(a: T, b: T) = function(a, b) - } -} -/** - * Compares two values using the specified functions [selectors] to calculate the result of the comparison. - * The functions are called sequentially, receive the given values [a] and [b] and return [Comparable] - * objects. As soon as the [Comparable] instances returned by a function for [a] and [b] values do not - * compare as equal, the result of that comparison is returned. - */ -public fun compareValuesBy(a: T, b: T, vararg selectors: (T) -> Comparable<*>?): Int { - require(selectors.size > 0) - for (fn in selectors) { - val v1 = fn(a) - val v2 = fn(b) - val diff = compareValues(v1, v2) - if (diff != 0) return diff - } - return 0 -} - -/** - * Compares two values using the specified [selector] function to calculate the result of the comparison. - * The function is applied to the given values [a] and [b] and return [Comparable] objects. - * The result of comparison of these [Comparable] instances is returned. - */ -@kotlin.internal.InlineOnly -public inline fun compareValuesBy(a: T, b: T, selector: (T) -> Comparable<*>?): Int { - return compareValues(selector(a), selector(b)) -} - -/** - * Compares two values using the specified [selector] function to calculate the result of the comparison. - * The function is applied to the given values [a] and [b] and return objects of type K which are then being - * compared with the given [comparator]. - */ -@kotlin.internal.InlineOnly -public inline fun compareValuesBy(a: T, b: T, comparator: Comparator, selector: (T) -> K): Int { - return comparator.compare(selector(a), selector(b)) -} - -//// Not so useful without type inference for receiver of expression -//// compareValuesWith(v1, v2, compareBy { it.prop1 } thenByDescending { it.prop2 }) -///** -// * Compares two values using the specified [comparator]. -// */ -//@Suppress("NOTHING_TO_INLINE") -//public inline fun compareValuesWith(a: T, b: T, comparator: Comparator): Int = comparator.compare(a, b) -// - - -/** - * Compares two nullable [Comparable] values. Null is considered less than any value. - */ -public fun > compareValues(a: T?, b: T?): Int { - if (a === b) return 0 - if (a == null) return -1 - if (b == null) return 1 - - @Suppress("UNCHECKED_CAST") - return (a as Comparable).compareTo(b) -} - -/** - * Creates a comparator using the sequence of functions to calculate a result of comparison. - * The functions are called sequentially, receive the given values `a` and `b` and return [Comparable] - * objects. As soon as the [Comparable] instances returned by a function for `a` and `b` values do not - * compare as equal, the result of that comparison is returned from the [Comparator]. - */ -public fun compareBy(vararg selectors: (T) -> Comparable<*>?): Comparator { - return object : Comparator { - public override fun compare(a: T, b: T): Int = compareValuesBy(a, b, *selectors) - } -} - - - -/** - * Creates a comparator using the function to transform value to a [Comparable] instance for comparison. - */ -@kotlin.internal.InlineOnly -public inline fun compareBy(crossinline selector: (T) -> Comparable<*>?): Comparator { - return object : Comparator { - public override fun compare(a: T, b: T): Int = compareValuesBy(a, b, selector) - } -} - -/** - * Creates a comparator using the [selector] function to transform values being compared and then applying - * the specified [comparator] to compare transformed values. - */ -@kotlin.internal.InlineOnly -public inline fun compareBy(comparator: Comparator, crossinline selector: (T) -> K): Comparator { - return object : Comparator { - public override fun compare(a: T, b: T): Int = compareValuesBy(a, b, comparator, selector) - } -} - -/** - * Creates a descending comparator using the function to transform value to a [Comparable] instance for comparison. - */ -@kotlin.internal.InlineOnly -public inline fun compareByDescending(crossinline selector: (T) -> Comparable<*>?): Comparator { - return object : Comparator { - public override fun compare(a: T, b: T): Int = compareValuesBy(b, a, selector) - } -} - -/** - * Creates a descending comparator using the [selector] function to transform values being compared and then applying - * the specified [comparator] to compare transformed values. - * - * Note that an order of [comparator] is reversed by this wrapper. - */ -@kotlin.internal.InlineOnly -public inline fun compareByDescending(comparator: Comparator, crossinline selector: (T) -> K): Comparator { - return object : Comparator { - public override fun compare(a: T, b: T): Int = compareValuesBy(b, a, comparator, selector) - } -} - -/** - * Creates a comparator comparing values after the primary comparator defined them equal. It uses - * the function to transform value to a [Comparable] instance for comparison. - */ -@kotlin.internal.InlineOnly -public inline fun Comparator.thenBy(crossinline selector: (T) -> Comparable<*>?): Comparator { - return object : Comparator { - public override fun compare(a: T, b: T): Int { - val previousCompare = this@thenBy.compare(a, b) - return if (previousCompare != 0) previousCompare else compareValuesBy(a, b, selector) - } - } -} - -/** - * Creates a comparator comparing values after the primary comparator defined them equal. It uses - * the [selector] function to transform values and then compares them with the given [comparator]. - */ -@kotlin.internal.InlineOnly -public inline fun Comparator.thenBy(comparator: Comparator, crossinline selector: (T) -> K): Comparator { - return object : Comparator { - public override fun compare(a: T, b: T): Int { - val previousCompare = this@thenBy.compare(a, b) - return if (previousCompare != 0) previousCompare else compareValuesBy(a, b, comparator, selector) - } - } -} - -/** - * Creates a descending comparator using the primary comparator and - * the function to transform value to a [Comparable] instance for comparison. - */ -@kotlin.internal.InlineOnly -public inline fun Comparator.thenByDescending(crossinline selector: (T) -> Comparable<*>?): Comparator { - return object : Comparator { - public override fun compare(a: T, b: T): Int { - val previousCompare = this@thenByDescending.compare(a, b) - return if (previousCompare != 0) previousCompare else compareValuesBy(b, a, selector) - } - } -} - -/** - * Creates a descending comparator comparing values after the primary comparator defined them equal. It uses - * the [selector] function to transform values and then compares them with the given [comparator]. - */ -@kotlin.internal.InlineOnly -public inline fun Comparator.thenByDescending(comparator: Comparator, crossinline selector: (T) -> K): Comparator { - return object : Comparator { - public override fun compare(a: T, b: T): Int { - val previousCompare = this@thenByDescending.compare(a, b) - return if (previousCompare != 0) previousCompare else compareValuesBy(b, a, comparator, selector) - } - } -} - - -/** - * Creates a comparator using the primary comparator and function to calculate a result of comparison. - */ -@kotlin.internal.InlineOnly -public inline fun Comparator.thenComparator(crossinline comparison: (T, T) -> Int): Comparator { - return object : Comparator { - public override fun compare(a: T, b: T): Int { - val previousCompare = this@thenComparator.compare(a, b) - return if (previousCompare != 0) previousCompare else comparison(a, b) - } - } -} - -/** - * Combines this comparator and the given [comparator] such that the latter is applied only - * when the former considered values equal. - */ -public infix fun Comparator.then(comparator: Comparator): Comparator { - return object : Comparator { - public override fun compare(a: T, b: T): Int { - val previousCompare = this@then.compare(a, b) - return if (previousCompare != 0) previousCompare else comparator.compare(a, b) - } - } -} - -/** - * Combines this comparator and the given [comparator] such that the latter is applied only - * when the former considered values equal. - */ -public infix fun Comparator.thenDescending(comparator: Comparator): Comparator { - return object : Comparator { - public override fun compare(a: T, b: T): Int { - val previousCompare = this@thenDescending.compare(a, b) - return if (previousCompare != 0) previousCompare else comparator.compare(b, a) - } - } -} - -// Not so useful without type inference for receiver of expression -/** - * Extends the given [comparator] of non-nullable values to a comparator of nullable values - * considering `null` value less than any other value. - */ -public fun nullsFirst(comparator: Comparator): Comparator { - return object: Comparator { - override fun compare(a: T?, b: T?): Int { - if (a === b) return 0 - if (a == null) return -1 - if (b == null) return 1 - return comparator.compare(a, b) - } - } -} - -/** - * Provides a comparator of nullable [Comparable] values - * considering `null` value less than any other value. - */ -@kotlin.internal.InlineOnly -public inline fun > nullsFirst(): Comparator = nullsFirst(naturalOrder()) - -/** - * Extends the given [comparator] of non-nullable values to a comparator of nullable values - * considering `null` value greater than any other value. - */ -public fun nullsLast(comparator: Comparator): Comparator { - return object: Comparator { - override fun compare(a: T?, b: T?): Int { - if (a === b) return 0 - if (a == null) return 1 - if (b == null) return -1 - return comparator.compare(a, b) - } - } -} - -/** - * Provides a comparator of nullable [Comparable] values - * considering `null` value greater than any other value. - */ -@kotlin.internal.InlineOnly -public inline fun > nullsLast(): Comparator = nullsLast(naturalOrder()) - -/** - * Returns a comparator that compares [Comparable] objects in natural order. - */ -public fun > naturalOrder(): Comparator = @Suppress("UNCHECKED_CAST") (NaturalOrderComparator as Comparator) - -/** - * Returns a comparator that compares [Comparable] objects in reversed natural order. - */ -public fun > reverseOrder(): Comparator = @Suppress("UNCHECKED_CAST") (ReverseOrderComparator as Comparator) - -/** Returns a comparator that imposes the reverse ordering of this comparator. */ -public fun Comparator.reversed(): Comparator = when (this) { - is ReversedComparator -> this.comparator - NaturalOrderComparator -> @Suppress("UNCHECKED_CAST") (ReverseOrderComparator as Comparator) - ReverseOrderComparator -> @Suppress("UNCHECKED_CAST") (NaturalOrderComparator as Comparator) - else -> ReversedComparator(this) -} - - -private class ReversedComparator(public val comparator: Comparator): Comparator { - override fun compare(a: T, b: T): Int = comparator.compare(b, a) - @Suppress("VIRTUAL_MEMBER_HIDDEN") - fun reversed(): Comparator = comparator -} - -private object NaturalOrderComparator : Comparator> { - override fun compare(a: Comparable, b: Comparable): Int = a.compareTo(b) - @Suppress("VIRTUAL_MEMBER_HIDDEN") - fun reversed(): Comparator> = ReverseOrderComparator -} - -private object ReverseOrderComparator: Comparator> { - override fun compare(a: Comparable, b: Comparable): Int = b.compareTo(a) - @Suppress("VIRTUAL_MEMBER_HIDDEN") - fun reversed(): Comparator> = NaturalOrderComparator -} - -// From _Comparisions.kt. +// Implements expects from _Comparisions.kt. /** * Returns the greater of two values. * If values are equal, returns the first one. */ @SinceKotlin("1.1") -public fun > maxOf(a: T, b: T): T { +public actual fun > maxOf(a: T, b: T): T { return if (a >= b) a else b } @@ -336,7 +32,7 @@ public fun > maxOf(a: T, b: T): T { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun maxOf(a: Byte, b: Byte): Byte { +public inline actual fun maxOf(a: Byte, b: Byte): Byte { return maxOf(a.toInt(), b.toInt()).toByte() } @@ -345,7 +41,7 @@ public inline fun maxOf(a: Byte, b: Byte): Byte { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun maxOf(a: Short, b: Short): Short { +public inline actual fun maxOf(a: Short, b: Short): Short { return maxOf(a.toInt(), b.toInt()).toShort() } @@ -354,7 +50,7 @@ public inline fun maxOf(a: Short, b: Short): Short { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun maxOf(a: Int, b: Int): Int { +public inline actual fun maxOf(a: Int, b: Int): Int { return if (a >= b) a else b } @@ -363,7 +59,7 @@ public inline fun maxOf(a: Int, b: Int): Int { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun maxOf(a: Long, b: Long): Long { +public inline actual fun maxOf(a: Long, b: Long): Long { return if (a >= b) a else b } @@ -372,7 +68,7 @@ public inline fun maxOf(a: Long, b: Long): Long { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun maxOf(a: Float, b: Float): Float { +public inline actual fun maxOf(a: Float, b: Float): Float { // According to http://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#max-float-float- // return NaN if one of the args is NaN. // TODO: Check +/-0.0 @@ -388,7 +84,7 @@ public inline fun maxOf(a: Float, b: Float): Float { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun maxOf(a: Double, b: Double): Double { +public inline actual fun maxOf(a: Double, b: Double): Double { return when { a.isNaN() -> a b.isNaN() -> b @@ -400,7 +96,7 @@ public inline fun maxOf(a: Double, b: Double): Double { * Returns the greater of three values. */ @SinceKotlin("1.1") -public fun > maxOf(a: T, b: T, c: T): T { +public actual fun > maxOf(a: T, b: T, c: T): T { return maxOf(a, maxOf(b, c)) } @@ -409,7 +105,7 @@ public fun > maxOf(a: T, b: T, c: T): T { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun maxOf(a: Byte, b: Byte, c: Byte): Byte { +public inline actual fun maxOf(a: Byte, b: Byte, c: Byte): Byte { return maxOf(a.toInt(), maxOf(b.toInt(), c.toInt())).toByte() } @@ -418,7 +114,7 @@ public inline fun maxOf(a: Byte, b: Byte, c: Byte): Byte { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun maxOf(a: Short, b: Short, c: Short): Short { +public inline actual fun maxOf(a: Short, b: Short, c: Short): Short { return maxOf(a.toInt(), maxOf(b.toInt(), c.toInt())).toShort() } @@ -427,7 +123,7 @@ public inline fun maxOf(a: Short, b: Short, c: Short): Short { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun maxOf(a: Int, b: Int, c: Int): Int { +public inline actual fun maxOf(a: Int, b: Int, c: Int): Int { return maxOf(a, maxOf(b, c)) } @@ -436,7 +132,7 @@ public inline fun maxOf(a: Int, b: Int, c: Int): Int { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun maxOf(a: Long, b: Long, c: Long): Long { +public inline actual fun maxOf(a: Long, b: Long, c: Long): Long { return maxOf(a, maxOf(b, c)) } @@ -445,7 +141,7 @@ public inline fun maxOf(a: Long, b: Long, c: Long): Long { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun maxOf(a: Float, b: Float, c: Float): Float { +public inline actual fun maxOf(a: Float, b: Float, c: Float): Float { return maxOf(a, maxOf(b, c)) } @@ -454,33 +150,16 @@ public inline fun maxOf(a: Float, b: Float, c: Float): Float { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun maxOf(a: Double, b: Double, c: Double): Double { +public inline actual fun maxOf(a: Double, b: Double, c: Double): Double { return maxOf(a, maxOf(b, c)) } -/** - * Returns the greater of three values according to the order specified by the given [comparator]. - */ -@SinceKotlin("1.1") -public fun maxOf(a: T, b: T, c: T, comparator: Comparator): T { - return maxOf(a, maxOf(b, c, comparator), comparator) -} - -/** - * Returns the greater of two values according to the order specified by the given [comparator]. - * If values are equal, returns the first one. - */ -@SinceKotlin("1.1") -public fun maxOf(a: T, b: T, comparator: Comparator): T { - return if (comparator.compare(a, b) >= 0) a else b -} - /** * Returns the smaller of two values. * If values are equal, returns the first one. */ @SinceKotlin("1.1") -public fun > minOf(a: T, b: T): T { +public actual fun > minOf(a: T, b: T): T { return if (a <= b) a else b } @@ -489,7 +168,7 @@ public fun > minOf(a: T, b: T): T { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun minOf(a: Byte, b: Byte): Byte { +public inline actual fun minOf(a: Byte, b: Byte): Byte { return minOf(a.toInt(), b.toInt()).toByte() } @@ -498,7 +177,7 @@ public inline fun minOf(a: Byte, b: Byte): Byte { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun minOf(a: Short, b: Short): Short { +public inline actual fun minOf(a: Short, b: Short): Short { return minOf(a.toInt(), b.toInt()).toShort() } @@ -507,7 +186,7 @@ public inline fun minOf(a: Short, b: Short): Short { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun minOf(a: Int, b: Int): Int { +public inline actual fun minOf(a: Int, b: Int): Int { return if (a <= b) a else b } @@ -516,7 +195,7 @@ public inline fun minOf(a: Int, b: Int): Int { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun minOf(a: Long, b: Long): Long { +public inline actual fun minOf(a: Long, b: Long): Long { return if (a <= b) a else b } @@ -525,7 +204,7 @@ public inline fun minOf(a: Long, b: Long): Long { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun minOf(a: Float, b: Float): Float { +public inline actual fun minOf(a: Float, b: Float): Float { // According to http://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#min-float-float- // return NaN if one of the args is NaN. return when { @@ -540,7 +219,7 @@ public inline fun minOf(a: Float, b: Float): Float { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun minOf(a: Double, b: Double): Double { +public inline actual fun minOf(a: Double, b: Double): Double { return when { a.isNaN() -> a b.isNaN() -> b @@ -552,7 +231,7 @@ public inline fun minOf(a: Double, b: Double): Double { * Returns the smaller of three values. */ @SinceKotlin("1.1") -public fun > minOf(a: T, b: T, c: T): T { +public actual fun > minOf(a: T, b: T, c: T): T { return minOf(a, minOf(b, c)) } @@ -561,7 +240,7 @@ public fun > minOf(a: T, b: T, c: T): T { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun minOf(a: Byte, b: Byte, c: Byte): Byte { +public inline actual fun minOf(a: Byte, b: Byte, c: Byte): Byte { return minOf(a.toInt(), minOf(b.toInt(), c.toInt())).toByte() } @@ -570,7 +249,7 @@ public inline fun minOf(a: Byte, b: Byte, c: Byte): Byte { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun minOf(a: Short, b: Short, c: Short): Short { +public inline actual fun minOf(a: Short, b: Short, c: Short): Short { return minOf(a.toInt(), minOf(b.toInt(), c.toInt())).toShort() } @@ -579,7 +258,7 @@ public inline fun minOf(a: Short, b: Short, c: Short): Short { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun minOf(a: Int, b: Int, c: Int): Int { +public inline actual fun minOf(a: Int, b: Int, c: Int): Int { return minOf(a, minOf(b, c)) } @@ -588,7 +267,7 @@ public inline fun minOf(a: Int, b: Int, c: Int): Int { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun minOf(a: Long, b: Long, c: Long): Long { +public inline actual fun minOf(a: Long, b: Long, c: Long): Long { return minOf(a, minOf(b, c)) } @@ -597,7 +276,7 @@ public inline fun minOf(a: Long, b: Long, c: Long): Long { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun minOf(a: Float, b: Float, c: Float): Float { +public inline actual fun minOf(a: Float, b: Float, c: Float): Float { return minOf(a, minOf(b, c)) } @@ -606,23 +285,7 @@ public inline fun minOf(a: Float, b: Float, c: Float): Float { */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun minOf(a: Double, b: Double, c: Double): Double { +public inline actual fun minOf(a: Double, b: Double, c: Double): Double { return minOf(a, minOf(b, c)) } -/** - * Returns the smaller of three values according to the order specified by the given [comparator]. - */ -@SinceKotlin("1.1") -public fun minOf(a: T, b: T, c: T, comparator: Comparator): T { - return minOf(a, minOf(b, c, comparator), comparator) -} - -/** - * Returns the smaller of two values according to the order specified by the given [comparator]. - * If values are equal, returns the first one. - */ -@SinceKotlin("1.1") -public fun minOf(a: T, b: T, comparator: Comparator): T { - return if (comparator.compare(a, b) <= 0) a else b -} diff --git a/runtime/src/main/kotlin/kotlin/coroutines/experimental/ContinuationInterceptor.kt b/runtime/src/main/kotlin/kotlin/coroutines/experimental/ContinuationInterceptor.kt deleted file mode 100644 index 6bc31a1d1af..00000000000 --- a/runtime/src/main/kotlin/kotlin/coroutines/experimental/ContinuationInterceptor.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.coroutines.experimental - -/** - * Marks coroutine context element that intercepts coroutine continuations. - * The coroutines framework uses [ContinuationInterceptor.Key] to retrieve the interceptor and - * intercepts all coroutine continuations with [interceptContinuation] invocations. - */ -public interface ContinuationInterceptor : CoroutineContext.Element { - /** - * The key that defines *the* context interceptor. - */ - companion object Key : CoroutineContext.Key - - /** - * Returns continuation that wraps the original [continuation], thus intercepting all resumptions. - * This function is invoked by coroutines framework when needed and the resulting continuations are - * cached internally per each instance of the original [continuation]. - * - * By convention, implementations that install themselves as *the* interceptor in the context with - * the [Key] shall also scan the context for other element that implement [ContinuationInterceptor] interface - * and use their [interceptContinuation] functions, too. - */ - public fun interceptContinuation(continuation: Continuation): Continuation -} diff --git a/runtime/src/main/kotlin/kotlin/coroutines/experimental/CoroutineContext.kt b/runtime/src/main/kotlin/kotlin/coroutines/experimental/CoroutineContext.kt deleted file mode 100644 index 836b23f3435..00000000000 --- a/runtime/src/main/kotlin/kotlin/coroutines/experimental/CoroutineContext.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.coroutines.experimental - -/** - * Persistent context for the coroutine. It is an indexed set of [Element] instances. - * An indexed set is a mix between a set and a map. - * Every element in this set has a unique [Key]. Keys are compared _by reference_. - */ -public interface CoroutineContext { - /** - * Returns the element with the given [key] from this context or `null`. - * Keys are compared _by reference_, that is to get an element from the context the reference to its actual key - * object must be presented to this function. - */ - public operator fun get(key: Key): E? - - /** - * Accumulates entries of this context starting with [initial] value and applying [operation] - * from left to right to current accumulator value and each element of this context. - */ - public fun fold(initial: R, operation: (R, Element) -> R): R - - /** - * Returns a context containing elements from this context and elements from other [context]. - * The elements from this context with the same key as in the other one are dropped. - */ - public operator fun plus(context: CoroutineContext): CoroutineContext - - /** - * Returns a context containing elements from this context, but without an element with - * the specified [key]. Keys are compared _by reference_, that is to remove an element from the context - * the reference to its actual key object must be presented to this function. - */ - public fun minusKey(key: Key<*>): CoroutineContext - - /** - * An element of the [CoroutineContext]. An element of the coroutine context is a singleton context by itself. - */ - public interface Element : CoroutineContext { - /** - * A key of this coroutine context element. - */ - public val key: Key<*> - } - - /** - * Key for the elements of [CoroutineContext]. [E] is a type of element with this key. - * Keys in the context are compared _by reference_. - */ - public interface Key -} diff --git a/runtime/src/main/kotlin/kotlin/coroutines/experimental/Coroutines.kt b/runtime/src/main/kotlin/kotlin/coroutines/experimental/Coroutines.kt deleted file mode 100644 index 0fa1fb02dc3..00000000000 --- a/runtime/src/main/kotlin/kotlin/coroutines/experimental/Coroutines.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.coroutines.experimental - -/** - * Interface representing a continuation after a suspension point that returns value of type `T`. - */ -public interface Continuation { - /** - * Context of the coroutine that corresponds to this continuation. - */ - public val context: CoroutineContext - - /** - * Resumes the execution of the corresponding coroutine passing [value] as the return value of the last suspension point. - */ - public fun resume(value: T) - - /** - * Resumes the execution of the corresponding coroutine so that the [exception] is re-thrown right after the - * last suspension point. - */ - public fun resumeWithException(exception: Throwable) -} - -/** - * Classes and interfaces marked with this annotation are restricted when used as receivers for extension - * `suspend` functions. These `suspend` extensions can only invoke other member or extension `suspend` functions on this particular - * receiver only and are restricted from calling arbitrary suspension functions. - */ -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.BINARY) -public annotation class RestrictsSuspension diff --git a/runtime/src/main/kotlin/kotlin/coroutines/experimental/CoroutinesLibrary.kt b/runtime/src/main/kotlin/kotlin/coroutines/experimental/CoroutinesLibrary.kt deleted file mode 100644 index c85bfbbb0f4..00000000000 --- a/runtime/src/main/kotlin/kotlin/coroutines/experimental/CoroutinesLibrary.kt +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.coroutines.experimental - -import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED -import kotlin.coroutines.experimental.intrinsics.suspendCoroutineOrReturn -import kotlin.coroutines.experimental.intrinsics.createCoroutineUnchecked -import konan.internal.SafeContinuation - -/** - * Starts coroutine with receiver type [R] and result type [T]. - * This function creates and start a new, fresh instance of suspendable computation every time it is invoked. - * The [completion] continuation is invoked when coroutine completes with result or exception. - */ -@Suppress("UNCHECKED_CAST") -public fun (suspend R.() -> T).startCoroutine( - receiver: R, - completion: Continuation -) { - createCoroutineUnchecked(receiver, completion).resume(Unit) -} - -/** - * Starts coroutine without receiver and with result type [T]. - * This function creates and start a new, fresh instance of suspendable computation every time it is invoked. - * The [completion] continuation is invoked when coroutine completes with result or exception. - */ -@Suppress("UNCHECKED_CAST") -public fun (suspend () -> T).startCoroutine( - completion: Continuation -) { - createCoroutineUnchecked(completion).resume(Unit) -} - -/** - * Creates a coroutine with receiver type [R] and result type [T]. - * This function creates a new, fresh instance of suspendable computation every time it is invoked. - * - * To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance. - * The [completion] continuation is invoked when coroutine completes with result or exception. - * Repeated invocation of any resume function on the resulting continuation produces [IllegalStateException]. - */ -@Suppress("UNCHECKED_CAST") -public fun (suspend R.() -> T).createCoroutine( - receiver: R, - completion: Continuation -): Continuation = SafeContinuation(createCoroutineUnchecked(receiver, completion), COROUTINE_SUSPENDED) - -/** - * Creates a coroutine without receiver and with result type [T]. - * This function creates a new, fresh instance of suspendable computation every time it is invoked. - * - * To start executing the created coroutine, invoke `resume(Unit)` on the returned [Continuation] instance. - * The [completion] continuation is invoked when coroutine completes with result or exception. - * Repeated invocation of any resume function on the resulting continuation produces [IllegalStateException]. - */ -@Suppress("UNCHECKED_CAST") -public fun (suspend () -> T).createCoroutine( - completion: Continuation -): Continuation = SafeContinuation(createCoroutineUnchecked(completion), COROUTINE_SUSPENDED) - -/** - * Obtains the current continuation instance inside suspend functions and suspends - * currently running coroutine. - * - * In this function both [Continuation.resume] and [Continuation.resumeWithException] can be used either synchronously in - * the same stack-frame where suspension function is run or asynchronously later in the same thread or - * from a different thread of execution. Repeated invocation of any resume function produces [IllegalStateException]. - */ -public inline suspend fun suspendCoroutine(crossinline block: (Continuation) -> Unit): T = - suspendCoroutineOrReturn { c: Continuation -> - val safe = SafeContinuation(c) - block(safe) - safe.getResult() - } - -// INTERNAL DECLARATIONS - -@kotlin.internal.InlineOnly -internal inline fun processBareContinuationResume(completion: Continuation<*>, block: () -> Any?) { - try { - val result = block() - if (result !== COROUTINE_SUSPENDED) { - @Suppress("UNCHECKED_CAST") (completion as Continuation).resume(result) - } - } catch (t: Throwable) { - completion.resumeWithException(t) - } -} diff --git a/runtime/src/main/kotlin/kotlin/coroutines/experimental/EmptyCoroutineContext.kt b/runtime/src/main/kotlin/kotlin/coroutines/experimental/EmptyCoroutineContext.kt deleted file mode 100644 index 76bc6f2312e..00000000000 --- a/runtime/src/main/kotlin/kotlin/coroutines/experimental/EmptyCoroutineContext.kt +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.coroutines.experimental - -import kotlin.coroutines.experimental.CoroutineContext.* - -/** - * Base class for [CoroutineContext.Element] implementations. - */ -public abstract class AbstractCoroutineContextElement(public override val key: Key<*>) : Element { - @Suppress("UNCHECKED_CAST") - public override operator fun get(key: Key): E? = - if (this.key === key) this as E else null - - public override fun fold(initial: R, operation: (R, Element) -> R): R = - operation(initial, this) - - public override operator fun plus(context: CoroutineContext): CoroutineContext = - plusImpl(context) - - public override fun minusKey(key: Key<*>): CoroutineContext = - if (this.key === key) EmptyCoroutineContext else this -} - -/** - * An empty coroutine context. - */ -public object EmptyCoroutineContext : CoroutineContext { - public override fun get(key: Key): E? = null - public override fun fold(initial: R, operation: (R, Element) -> R): R = initial - public override fun plus(context: CoroutineContext): CoroutineContext = context - public override fun minusKey(key: Key<*>): CoroutineContext = this - public override fun hashCode(): Int = 0 - public override fun toString(): String = "EmptyCoroutineContext" -} - -//--------------------- private impl --------------------- - -// this class is not exposed, but is hidden inside implementations -// this is a left-biased list, so that `plus` works naturally -private class CombinedContext(val left: CoroutineContext, val element: Element) : CoroutineContext { - override fun get(key: Key): E? { - var cur = this - while (true) { - cur.element[key]?.let { return it } - val next = cur.left - if (next is CombinedContext) { - cur = next - } else { - return next[key] - } - } - } - - public override fun fold(initial: R, operation: (R, Element) -> R): R = - operation(left.fold(initial, operation), element) - - public override operator fun plus(context: CoroutineContext): CoroutineContext = - plusImpl(context) - - public override fun minusKey(key: Key<*>): CoroutineContext { - element[key]?.let { return left } - val newLeft = left.minusKey(key) - return when { - newLeft === left -> this - newLeft === EmptyCoroutineContext -> element - else -> CombinedContext(newLeft, element) - } - } - - private fun size(): Int = - if (left is CombinedContext) left.size() + 1 else 2 - - private fun contains(element: Element): Boolean = - get(element.key) == element - - private fun containsAll(context: CombinedContext): Boolean { - var cur = context - while (true) { - if (!contains(cur.element)) return false - val next = cur.left - if (next is CombinedContext) { - cur = next - } else { - return contains(next as Element) - } - } - } - - override fun equals(other: Any?): Boolean = - this === other || other is CombinedContext && other.size() == size() && other.containsAll(this) - - override fun hashCode(): Int = left.hashCode() + element.hashCode() - - override fun toString(): String = - "[" + fold("") { acc, element -> - if (acc.isEmpty()) element.toString() else acc + ", " + element - } + "]" -} - -private fun CoroutineContext.plusImpl(context: CoroutineContext): CoroutineContext = - if (context === EmptyCoroutineContext) this else // fast path -- avoid lambda creation - context.fold(this) { acc, element -> - val removed = acc.minusKey(element.key) - if (removed === EmptyCoroutineContext) element else { - // make sure interceptor is always last in the context (and thus is fast to get when present) - val interceptor = removed[ContinuationInterceptor] - if (interceptor == null) CombinedContext(removed, element) else { - val left = removed.minusKey(ContinuationInterceptor) - if (left === EmptyCoroutineContext) CombinedContext(element, interceptor) else - CombinedContext(CombinedContext(left, element), interceptor) - } - } - } diff --git a/runtime/src/main/kotlin/kotlin/coroutines/experimental/intrinsics/Intrinsics.kt b/runtime/src/main/kotlin/kotlin/coroutines/experimental/Intrinsics.kt similarity index 71% rename from runtime/src/main/kotlin/kotlin/coroutines/experimental/intrinsics/Intrinsics.kt rename to runtime/src/main/kotlin/kotlin/coroutines/experimental/Intrinsics.kt index 77a8c96ca00..49a3537e96f 100644 --- a/runtime/src/main/kotlin/kotlin/coroutines/experimental/intrinsics/Intrinsics.kt +++ b/runtime/src/main/kotlin/kotlin/coroutines/experimental/Intrinsics.kt @@ -21,32 +21,6 @@ import kotlin.coroutines.experimental.CoroutineContext import kotlin.coroutines.experimental.processBareContinuationResume import konan.internal.* -/** - * Obtains the current continuation instance inside suspend functions and either suspend - * currently running coroutine or return result immediately without suspension. - * - * If the [block] returns the special [COROUTINE_SUSPENDED] value, it means that suspend function did suspend the execution and will - * not return any result immediately. In this case, the [Continuation] provided to the [block] shall be invoked at some moment in the - * future when the result becomes available to resume the computation. - * - * Otherwise, the return value of the [block] must have a type assignable to [T] and represents the result of this suspend function. - * It means that the execution was not suspended and the [Continuation] provided to the [block] shall not be invoked. - * As the result type of the [block] is declared as `Any?` and cannot be correctly type-checked, - * its proper return type remains on the conscience of the suspend function's author. - * - * Note that it is not recommended to call either [Continuation.resume] nor [Continuation.resumeWithException] functions synchronously - * in the same stackframe where suspension function is run. Use [suspendCoroutine] as a safer way to obtain current - * continuation instance. - */ -@kotlin.internal.InlineOnly -public inline suspend fun suspendCoroutineOrReturn(crossinline block: (Continuation) -> Any?): T = - returnIfSuspended(block(normalizeContinuation(getContinuation()))) - -/** - * This value is used as a return value of [suspendCoroutineOrReturn] `block` argument to state that - * the execution was suspended and will not return any result immediately. - */ -public val COROUTINE_SUSPENDED: Any = Any() /** * Creates a coroutine without receiver and with result type [T]. @@ -58,7 +32,7 @@ public val COROUTINE_SUSPENDED: Any = Any() * This function is _unchecked_. Repeated invocation of any resume function on the resulting continuation corrupts the * state machine of the coroutine and may result in arbitrary behaviour or exception. */ -public fun (suspend () -> T).createCoroutineUnchecked( +public actual fun (suspend () -> T).createCoroutineUnchecked( completion: Continuation ): Continuation = if (this !is CoroutineImpl) @@ -78,7 +52,7 @@ public fun (suspend () -> T).createCoroutineUnchecked( * This function is _unchecked_. Repeated invocation of any resume function on the resulting continuation corrupts the * state machine of the coroutine and may result in arbitrary behaviour or exception. */ -public fun (suspend R.() -> T).createCoroutineUnchecked( +public actual fun (suspend R.() -> T).createCoroutineUnchecked( receiver: R, completion: Continuation ): Continuation = @@ -122,7 +96,7 @@ private /*inline*/ fun buildContinuationByInvokeCall( */ @Suppress("UNCHECKED_CAST") @kotlin.internal.InlineOnly -public inline fun (suspend () -> T).startCoroutineUninterceptedOrReturn( +public actual inline fun (suspend () -> T).startCoroutineUninterceptedOrReturn( completion: Continuation ): Any? = (this as Function1, Any?>).invoke(completion) @@ -135,7 +109,7 @@ public inline fun (suspend () -> T).startCoroutineUninterceptedOrReturn( */ @Suppress("UNCHECKED_CAST") @kotlin.internal.InlineOnly -public inline fun (suspend R.() -> T).startCoroutineUninterceptedOrReturn( +public actual inline fun (suspend R.() -> T).startCoroutineUninterceptedOrReturn( receiver: R, completion: Continuation ): Any? = (this as Function2, Any?>).invoke(receiver, completion) diff --git a/runtime/src/main/kotlin/kotlin/coroutines/experimental/SafeContinuation.kt b/runtime/src/main/kotlin/kotlin/coroutines/experimental/SafeContinuation.kt new file mode 100644 index 00000000000..45c6969f114 --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/coroutines/experimental/SafeContinuation.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2010-2018 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 kotlin.coroutines.experimental + +import kotlin.coroutines.experimental.intrinsics.* + +// Single-threaded continuation. +@PublishedApi +internal final actual class SafeContinuation internal actual constructor( + private val delegate: Continuation, initialResult: Any?) : Continuation { + + @PublishedApi + internal actual constructor(delegate: Continuation) : this(delegate, UNDECIDED) + + actual override val context: CoroutineContext + get() = delegate.context + + private var result: Any? = initialResult + + companion object { + private val UNDECIDED: Any? = Any() + private val RESUMED: Any? = Any() + } + + private class Fail(val exception: Throwable) + + actual override fun resume(value: T) { + when { + result === UNDECIDED -> result = value + result === COROUTINE_SUSPENDED -> { + result = RESUMED + delegate.resume(value) + } + else -> throw IllegalStateException("Already resumed") + } + } + + actual override fun resumeWithException(exception: Throwable) { + when { + result === UNDECIDED -> result = Fail(exception) + result === COROUTINE_SUSPENDED -> { + result = RESUMED + delegate.resumeWithException(exception) + } + else -> throw IllegalStateException("Already resumed") + } + } + + @PublishedApi + internal actual fun getResult(): Any? { + if (this.result === UNDECIDED) this.result = COROUTINE_SUSPENDED + val result = this.result + when { + result === RESUMED -> return COROUTINE_SUSPENDED // already called continuation, indicate COROUTINE_SUSPENDED upstream + result is Fail -> throw result.exception + else -> return result // either COROUTINE_SUSPENDED or data + } + } +} \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/coroutines/experimental/SequenceBuilder.kt b/runtime/src/main/kotlin/kotlin/coroutines/experimental/SequenceBuilder.kt deleted file mode 100644 index 6cf7cdc5e06..00000000000 --- a/runtime/src/main/kotlin/kotlin/coroutines/experimental/SequenceBuilder.kt +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.coroutines.experimental - -import kotlin.coroutines.experimental.intrinsics.* - -/** - * Builds a [Sequence] lazily yielding values one by one. - * - * @see kotlin.sequences.generateSequence - * - * @sample samples.collections.Sequences.Building.buildSequenceYieldAll - * @sample samples.collections.Sequences.Building.buildFibonacciSequence - */ -public fun buildSequence(builderAction: suspend SequenceBuilder.() -> Unit): Sequence = Sequence { buildIterator(builderAction) } - -/** - * Builds an [Iterator] lazily yielding values one by one. - * - * @sample samples.collections.Sequences.Building.buildIterator - */ -public fun buildIterator(builderAction: suspend SequenceBuilder.() -> Unit): Iterator { - val iterator = SequenceBuilderIterator() - iterator.nextStep = builderAction.createCoroutineUnchecked(receiver = iterator, completion = iterator) - return iterator -} - -/** - * Builder for a [Sequence] or an [Iterator], provides [yield] and [yieldAll] suspension functions. - * - * @see buildSequence - * @see buildIterator - * - * @sample samples.collections.Sequences.Building.buildSequenceYieldAll - * @sample samples.collections.Sequences.Building.buildFibonacciSequence - */ -@RestrictsSuspension -public abstract class SequenceBuilder internal constructor() { - /** - * Yields a value to the [Iterator] being built. - * - * @sample samples.collections.Sequences.Building.buildSequenceYieldAll - * @sample samples.collections.Sequences.Building.buildFibonacciSequence - */ - public abstract suspend fun yield(value: T) - - /** - * Yields all values from the `iterator` to the [Iterator] being built. - * - * The sequence of values returned by the given iterator can be potentially infinite. - * - * @sample samples.collections.Sequences.Building.buildSequenceYieldAll - */ - public abstract suspend fun yieldAll(iterator: Iterator) - - /** - * Yields a collections of values to the [Iterator] being built. - * - * @sample samples.collections.Sequences.Building.buildSequenceYieldAll - */ - public suspend fun yieldAll(elements: Iterable) { - if (elements is Collection && elements.isEmpty()) return - return yieldAll(elements.iterator()) - } - - /** - * Yields potentially infinite sequence of values to the [Iterator] being built. - * - * The sequence can be potentially infinite. - * - * @sample samples.collections.Sequences.Building.buildSequenceYieldAll - */ - public suspend fun yieldAll(sequence: Sequence) = yieldAll(sequence.iterator()) -} - -private typealias State = Int -private const val State_NotReady: State = 0 -private const val State_ManyNotReady: State = 1 -private const val State_ManyReady: State = 2 -private const val State_Ready: State = 3 -private const val State_Done: State = 4 -private const val State_Failed: State = 5 - -private class SequenceBuilderIterator : SequenceBuilder(), Iterator, Continuation { - private var state = State_NotReady - private var nextValue: T? = null - private var nextIterator: Iterator? = null - var nextStep: Continuation? = null - - override fun hasNext(): Boolean { - while (true) { - when (state) { - State_NotReady -> {} - State_ManyNotReady -> - if (nextIterator!!.hasNext()) { - state = State_ManyReady - return true - } else { - nextIterator = null - } - State_Done -> return false - State_Ready, State_ManyReady -> return true - else -> throw exceptionalState() - } - - state = State_Failed - val step = nextStep!! - nextStep = null - step.resume(Unit) - } - } - - override fun next(): T { - when (state) { - State_NotReady, State_ManyNotReady -> return nextNotReady() - State_ManyReady -> { - state = State_ManyNotReady - return nextIterator!!.next() - } - State_Ready -> { - state = State_NotReady - @Suppress("UNCHECKED_CAST") - val result = nextValue as T - nextValue = null - return result - } - else -> throw exceptionalState() - } - } - - private fun nextNotReady(): T { - if (!hasNext()) throw NoSuchElementException() else return next() - } - - private fun exceptionalState(): Throwable = when (state) { - State_Done -> NoSuchElementException() - State_Failed -> IllegalStateException("Iterator has failed.") - else -> IllegalStateException("Unexpected state of the iterator: $state") - } - - - suspend override fun yield(value: T) { - nextValue = value - state = State_Ready - return suspendCoroutineOrReturn { c -> - nextStep = c - COROUTINE_SUSPENDED - } - } - - suspend override fun yieldAll(iterator: Iterator) { - if (!iterator.hasNext()) return - nextIterator = iterator - state = State_ManyReady - return suspendCoroutineOrReturn { c -> - nextStep = c - COROUTINE_SUSPENDED - } - } - - // Completion continuation implementation - override fun resume(value: Unit) { - state = State_Done - } - - override fun resumeWithException(exception: Throwable) { - throw exception // just rethrow - } - - override val context: CoroutineContext - get() = EmptyCoroutineContext -} diff --git a/runtime/src/main/kotlin/kotlin/internal/Annotations.kt b/runtime/src/main/kotlin/kotlin/internal/Annotations.kt index 696996b53b1..85dd367949c 100644 --- a/runtime/src/main/kotlin/kotlin/internal/Annotations.kt +++ b/runtime/src/main/kotlin/kotlin/internal/Annotations.kt @@ -16,52 +16,6 @@ package kotlin.internal -/** - * Specifies that the corresponding type should be ignored during type inference. - */ -@Target(AnnotationTarget.TYPE) -@Retention(AnnotationRetention.BINARY) -internal annotation class NoInfer - -/** - * Specifies that the constraint built for the type during type inference should be an equality one. - */ -@Target(AnnotationTarget.TYPE) -@Retention(AnnotationRetention.BINARY) -internal annotation class Exact - -/** - * Specifies that a corresponding member has the lowest priority in overload resolution. - */ -@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) -@Retention(AnnotationRetention.BINARY) -internal annotation class LowPriorityInOverloadResolution - -/** - * Specifies that the corresponding member has the highest priority in overload resolution. Effectively this means that - * an extension annotated with this annotation will win in overload resolution over a member with the same signature. - */ -@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) -@Retention(AnnotationRetention.BINARY) -internal annotation class HidesMembers - -/** - * The value of this type parameter should be mentioned in input types (argument types, receiver type or expected type). - */ -@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER) -public annotation class OnlyInputTypes - - -@Target(AnnotationTarget.TYPE, AnnotationTarget.TYPE_PARAMETER) -public annotation class OnlyOutputTypes - -/** - * Specifies that this function should not be called directly without inlining - */ -@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) -@Retention(AnnotationRetention.BINARY) -internal annotation class InlineOnly - /** * Specifies that this part of internal API is effectively public exposed by using in public inline function */ @@ -76,12 +30,3 @@ internal annotation class InlineExposed @Target(AnnotationTarget.TYPE_PARAMETER) @Retention(AnnotationRetention.BINARY) internal annotation class PureReifiable - -/** - * The value of this parameter should be a property reference expression (`this::foo`), referencing a `lateinit` property, - * the backing field of which is accessible at the point where the corresponding argument is passed. - */ -@Target(AnnotationTarget.VALUE_PARAMETER) -@Retention(AnnotationRetention.BINARY) -@SinceKotlin("1.2") -internal annotation class AccessibleLateinitPropertyLiteral diff --git a/runtime/src/main/kotlin/kotlin/io/Console.kt b/runtime/src/main/kotlin/kotlin/io/Console.kt index fa956d5b029..36195fbabde 100644 --- a/runtime/src/main/kotlin/kotlin/io/Console.kt +++ b/runtime/src/main/kotlin/kotlin/io/Console.kt @@ -24,7 +24,7 @@ public fun print(message: T) { print(message.toString()) } */ -public fun print(message: Any?) { +public actual fun print(message: Any?) { print(message.toString()) } @@ -63,7 +63,7 @@ public fun print(message: Boolean) { @SymbolName("Kotlin_io_Console_println") external public fun println(message: String) -public fun println(message: Any?) { +public actual fun println(message: Any?) { println(message.toString()) } @@ -104,7 +104,7 @@ public fun println(message: T) { } */ @SymbolName("Kotlin_io_Console_println0") -external public fun println() +external public actual fun println() @SymbolName("Kotlin_io_Console_readLine") external public fun readLine(): String? diff --git a/runtime/src/main/kotlin/kotlin/io/Serializable.kt b/runtime/src/main/kotlin/kotlin/io/Serializable.kt new file mode 100644 index 00000000000..e9f8c17bab1 --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/io/Serializable.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2018 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 kotlin.io + +// TODO: This interface is a temporary solution for common collections and not used in Native. +internal actual interface Serializable \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/jvm/JvmAnnotations.kt b/runtime/src/main/kotlin/kotlin/jvm/JvmAnnotations.kt new file mode 100644 index 00000000000..28cba3390e4 --- /dev/null +++ b/runtime/src/main/kotlin/kotlin/jvm/JvmAnnotations.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2018JetBrains 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 kotlin.jvm + +// Dummy JVM specific annotations in Kotlin/Native. Used in common stdlib. + +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.FILE) +actual annotation class JvmName(actual val name: String) + +@Target(AnnotationTarget.FILE) +actual annotation class JvmMultifileClass + +actual annotation class JvmField + +@Target(AnnotationTarget.FIELD) +actual annotation class Volatile \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/math/math.kt b/runtime/src/main/kotlin/kotlin/math/math.kt index 875f18d3785..2c9063c2d7e 100644 --- a/runtime/src/main/kotlin/kotlin/math/math.kt +++ b/runtime/src/main/kotlin/kotlin/math/math.kt @@ -16,17 +16,6 @@ package kotlin.math -// region ================ Constants ======================================== - -/** Ratio of the circumference of a circle to its diameter, approximately 3.14159. */ -@SinceKotlin("1.2") -public const val PI: Double = 3.141592653589793 -/** Base of the natural logarithms, approximately 2.71828. */ -@SinceKotlin("1.2") -public const val E: Double = 2.718281828459045 - -// endregion - // region ================ Double Math ======================================== /** Computes the sine of the angle [x] given in radians. @@ -36,7 +25,7 @@ public const val E: Double = 2.718281828459045 */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_sin") -external public fun sin(x: Double): Double +external public actual fun sin(x: Double): Double /** Computes the cosine of the angle [x] given in radians. * @@ -45,7 +34,7 @@ external public fun sin(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_cos") -external public fun cos(x: Double): Double +external public actual fun cos(x: Double): Double /** Computes the tangent of the angle [x] given in radians. * @@ -54,7 +43,7 @@ external public fun cos(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_tan") -external public fun tan(x: Double): Double +external public actual fun tan(x: Double): Double /** * Computes the arc sine of the value [x]; @@ -65,7 +54,7 @@ external public fun tan(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_asin") -external public fun asin(x: Double): Double +external public actual fun asin(x: Double): Double /** * Computes the arc cosine of the value [x]; @@ -76,7 +65,7 @@ external public fun asin(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_acos") -external public fun acos(x: Double): Double +external public actual fun acos(x: Double): Double /** * Computes the arc tangent of the value [x]; @@ -87,7 +76,7 @@ external public fun acos(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_atan") -external public fun atan(x: Double): Double +external public actual fun atan(x: Double): Double /** * Returns the angle `theta` of the polar coordinates `(r, theta)` that correspond @@ -107,7 +96,7 @@ external public fun atan(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_atan2") -external public fun atan2(y: Double, x: Double): Double +external public actual fun atan2(y: Double, x: Double): Double /** * Computes the hyperbolic sine of the value [x]. @@ -119,7 +108,7 @@ external public fun atan2(y: Double, x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_sinh") -external public fun sinh(x: Double): Double +external public actual fun sinh(x: Double): Double /** * Computes the hyperbolic cosine of the value [x]. @@ -130,7 +119,7 @@ external public fun sinh(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_cosh") -external public fun cosh(x: Double): Double +external public actual fun cosh(x: Double): Double /** * Computes the hyperbolic tangent of the value [x]. @@ -142,7 +131,7 @@ external public fun cosh(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_tanh") -external public fun tanh(x: Double): Double +external public actual fun tanh(x: Double): Double /** * Computes the inverse hyperbolic sine of the value [x]. @@ -156,7 +145,7 @@ external public fun tanh(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_asinh") -external public fun asinh(x: Double): Double +external public actual fun asinh(x: Double): Double /** * Computes the inverse hyperbolic cosine of the value [x]. @@ -170,7 +159,7 @@ external public fun asinh(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_acosh") -external public fun acosh(x: Double): Double +external public actual fun acosh(x: Double): Double /** * Computes the inverse hyperbolic tangent of the value [x]. @@ -185,7 +174,7 @@ external public fun acosh(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_atanh") -external public fun atanh(x: Double): Double +external public actual fun atanh(x: Double): Double /** * Computes `sqrt(x^2 + y^2)` without intermediate overflow or underflow. @@ -196,7 +185,7 @@ external public fun atanh(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_hypot") -external public fun hypot(x: Double, y: Double): Double +external public actual fun hypot(x: Double, y: Double): Double /** * Computes the positive square root of the value [x]. @@ -206,7 +195,7 @@ external public fun hypot(x: Double, y: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_sqrt") -external public fun sqrt(x: Double): Double +external public actual fun sqrt(x: Double): Double /** * Computes Euler's number `e` raised to the power of the value [x]. @@ -218,23 +207,23 @@ external public fun sqrt(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_exp") -external public fun exp(x: Double): Double +external public actual fun exp(x: Double): Double /** * Computes `exp(x) - 1`. * - * This function can be implemented to produce more precise result for [x] near zero. + * This actual function can be implemented to produce more precise result for [x] near zero. * * Special cases: * - `expm1(NaN)` is `NaN` * - `expm1(+Inf)` is `+Inf` * - `expm1(-Inf)` is `-1.0` * - * @see [exp] function. + * @see [exp] actual function. */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_expm1") -external public fun expm1(x: Double): Double +external public actual fun expm1(x: Double): Double /** * Computes the logarithm of the value [x] to the given [base]. @@ -246,10 +235,10 @@ external public fun expm1(x: Double): Double * - `log(+Inf, b)` is `+Inf` for `b > 1` and `-Inf` for `b < 1` * - `log(0.0, b)` is `-Inf` for `b > 1` and `+Inf` for `b > 1` * - * See also logarithm functions for common fixed bases: [ln], [log10] and [log2]. + * See also logarithm actual functions for common fixed bases: [ln], [log10] and [log2]. */ @SinceKotlin("1.2") -public fun log(x: Double, base: Double): Double { +public actual fun log(x: Double, base: Double): Double { if (base <= 0.0 || base == 1.0) return Double.NaN return ln(x) / ln(base) } @@ -265,30 +254,30 @@ public fun log(x: Double, base: Double): Double { */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_ln") -external public fun ln(x: Double): Double +external public actual fun ln(x: Double): Double /** * Computes the common logarithm (base 10) of the value [x]. * - * @see [ln] function for special cases. + * @see [ln] actual function for special cases. */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_log10") -external public fun log10(x: Double): Double +external public actual fun log10(x: Double): Double /** * Computes the binary logarithm (base 2) of the value [x]. * - * @see [ln] function for special cases. + * @see [ln] actual function for special cases. */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_log2") -external public fun log2(x: Double): Double +external public actual fun log2(x: Double): Double /** * Computes `ln(x + 1)`. * - * This function can be implemented to produce more precise result for [x] near zero. + * This actual function can be implemented to produce more precise result for [x] near zero. * * Special cases: * - `ln1p(NaN)` is `NaN` @@ -296,12 +285,12 @@ external public fun log2(x: Double): Double * - `ln1p(-1.0)` is `-Inf` * - `ln1p(+Inf)` is `+Inf` * - * @see [ln] function - * @see [expm1] function + * @see [ln] actual function + * @see [expm1] actual function */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_ln1p") -external public fun ln1p(x: Double): Double +external public actual fun ln1p(x: Double): Double /** * Rounds the given value [x] to an integer towards positive infinity. @@ -313,7 +302,7 @@ external public fun ln1p(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_ceil") -external public fun ceil(x: Double): Double +external public actual fun ceil(x: Double): Double /** * Rounds the given value [x] to an integer towards negative infinity. @@ -325,7 +314,7 @@ external public fun ceil(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_floor") -external public fun floor(x: Double): Double +external public actual fun floor(x: Double): Double /** * Rounds the given value [x] to an integer towards zero. @@ -336,7 +325,7 @@ external public fun floor(x: Double): Double * - `truncate(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. */ @SinceKotlin("1.2") -public fun truncate(x: Double): Double = when { +public actual fun truncate(x: Double): Double = when { x.isNaN() || x.isInfinite() -> x x > 0 -> floor(x) else -> ceil(x) @@ -350,7 +339,7 @@ public fun truncate(x: Double): Double = when { */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_round") -external public fun round(x: Double): Double +external public actual fun round(x: Double): Double /** * Returns the absolute value of the given value [x]. @@ -362,7 +351,7 @@ external public fun round(x: Double): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_abs") -external public fun abs(x: Double): Double +external public actual fun abs(x: Double): Double /** * Returns the sign of the given value [x]: @@ -374,7 +363,7 @@ external public fun abs(x: Double): Double * - `sign(NaN)` is `NaN` */ @SinceKotlin("1.2") -public fun sign(x: Double): Double = when { +public actual fun sign(x: Double): Double = when { x.isNaN() -> Double.NaN x > 0 -> 1.0 x < 0 -> -1.0 @@ -387,7 +376,7 @@ public fun sign(x: Double): Double = when { * If either value is `NaN`, then the result is `NaN`. */ @SinceKotlin("1.2") -public fun min(a: Double, b: Double): Double = when { +public actual fun min(a: Double, b: Double): Double = when { a.isNaN() || b.isNaN() -> Double.NaN a == 0.0 && b == 0.0 -> if (a.signBit()) a else b // -0.0 < +0.0 else -> if (a < b) a else b @@ -398,7 +387,7 @@ public fun min(a: Double, b: Double): Double = when { * If either value is `NaN`, then the result is `NaN`. */ @SinceKotlin("1.2") -public fun max(a: Double, b: Double): Double = when { +public actual fun max(a: Double, b: Double): Double = when { a.isNaN() || b.isNaN() -> Double.NaN a == 0.0 && b == 0.0 -> if (!a.signBit()) a else b // -0.0 < +0.0 else -> if (a > b) a else b @@ -419,7 +408,7 @@ public fun max(a: Double, b: Double): Double = when { */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_Double_pow") -external public fun Double.pow(x: Double): Double +external public actual fun Double.pow(x: Double): Double /** * Raises this value to the integer power [n]. @@ -427,7 +416,7 @@ external public fun Double.pow(x: Double): Double * See the other overload of [pow] for details. */ @SinceKotlin("1.2") -public fun Double.pow(n: Int): Double = pow(n.toDouble()) +public actual fun Double.pow(n: Int): Double = pow(n.toDouble()) /** * Computes the remainder of division of this value by the [divisor] value according to the IEEE 754 standard. @@ -451,10 +440,10 @@ external public fun Double.IEEErem(divisor: Double): Double * Special cases: * - `NaN.absoluteValue` is `NaN` * - * @see abs function + * @see abs actual function */ @SinceKotlin("1.2") -public val Double.absoluteValue: Double +public actual val Double.absoluteValue: Double get() = abs(this) /** @@ -467,7 +456,7 @@ public val Double.absoluteValue: Double * - `NaN.sign` is `NaN` */ @SinceKotlin("1.2") -public val Double.sign: Double +public actual val Double.sign: Double get() = sign(this) /** @@ -477,13 +466,13 @@ public val Double.sign: Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_Double_withSign") -external public fun Double.withSign(sign: Double): Double +external public actual fun Double.withSign(sign: Double): Double /** * Returns this value with the sign bit same as of the [sign] value. */ @SinceKotlin("1.2") -public fun Double.withSign(sign: Int): Double = withSign(sign.toDouble()) +public actual fun Double.withSign(sign: Int): Double = withSign(sign.toDouble()) /** * Returns the ulp (unit in the last place) of this value. @@ -496,7 +485,7 @@ public fun Double.withSign(sign: Int): Double = withSign(sign.toDouble()) * - `0.0.ulp` is `Double.MIN_VALUE` */ @SinceKotlin("1.2") -public val Double.ulp: Double +public actual val Double.ulp: Double get() = when { isNaN() -> Double.NaN isInfinite() -> Double.POSITIVE_INFINITY @@ -512,13 +501,13 @@ public val Double.ulp: Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_Double_nextUp") -external public fun Double.nextUp(): Double +external public actual fun Double.nextUp(): Double /** * Returns the [Double] value nearest to this value in direction of negative infinity. */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_Double_nextDown") -external public fun Double.nextDown(): Double +external public actual fun Double.nextDown(): Double /** * Returns the [Double] value nearest to this value in direction from this value towards the value [to]. @@ -530,7 +519,7 @@ external public fun Double.nextDown(): Double */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_Double_nextTowards") -external public fun Double.nextTowards(to: Double): Double +external public actual fun Double.nextTowards(to: Double): Double /** * Returns true if the sign of [this] value is negative and false otherwise @@ -549,7 +538,7 @@ external private fun Double.signBit(): Boolean * @throws IllegalArgumentException when this value is `NaN` */ @SinceKotlin("1.2") -public fun Double.roundToInt(): Int = when { +public actual fun Double.roundToInt(): Int = when { isNaN() -> throw IllegalArgumentException("Cannot round NaN value.") this > Int.MAX_VALUE -> Int.MAX_VALUE this < Int.MIN_VALUE -> Int.MIN_VALUE @@ -567,7 +556,7 @@ public fun Double.roundToInt(): Int = when { * @throws IllegalArgumentException when this value is `NaN` */ @SinceKotlin("1.2") -public fun Double.roundToLong(): Long = when { +public actual fun Double.roundToLong(): Long = when { isNaN() -> throw IllegalArgumentException("Cannot round NaN value.") this > Long.MAX_VALUE -> Long.MAX_VALUE this < Long.MIN_VALUE -> Long.MIN_VALUE @@ -585,7 +574,7 @@ public fun Double.roundToLong(): Long = when { */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_sinf") -external public fun sin(x: Float): Float +external public actual fun sin(x: Float): Float /** Computes the cosine of the angle [x] given in radians. * @@ -594,7 +583,7 @@ external public fun sin(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_cosf") -external public fun cos(x: Float): Float +external public actual fun cos(x: Float): Float /** Computes the tangent of the angle [x] given in radians. * @@ -603,7 +592,7 @@ external public fun cos(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_tanf") -external public fun tan(x: Float): Float +external public actual fun tan(x: Float): Float /** * Computes the arc sine of the value [x]; @@ -614,7 +603,7 @@ external public fun tan(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_asinf") -external public fun asin(x: Float): Float +external public actual fun asin(x: Float): Float /** * Computes the arc cosine of the value [x]; @@ -625,7 +614,7 @@ external public fun asin(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_acosf") -external public fun acos(x: Float): Float +external public actual fun acos(x: Float): Float /** * Computes the arc tangent of the value [x]; @@ -636,7 +625,7 @@ external public fun acos(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_atanf") -external public fun atan(x: Float): Float +external public actual fun atan(x: Float): Float /** * Returns the angle `theta` of the polar coordinates `(r, theta)` that correspond @@ -656,7 +645,7 @@ external public fun atan(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_atan2f") -external public fun atan2(y: Float, x: Float): Float +external public actual fun atan2(y: Float, x: Float): Float /** * Computes the hyperbolic sine of the value [x]. @@ -668,7 +657,7 @@ external public fun atan2(y: Float, x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_sinhf") -external public fun sinh(x: Float): Float +external public actual fun sinh(x: Float): Float /** * Computes the hyperbolic cosine of the value [x]. @@ -679,7 +668,7 @@ external public fun sinh(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_coshf") -external public fun cosh(x: Float): Float +external public actual fun cosh(x: Float): Float /** * Computes the hyperbolic tangent of the value [x]. @@ -691,7 +680,7 @@ external public fun cosh(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_tanhf") -external public fun tanh(x: Float): Float +external public actual fun tanh(x: Float): Float /** * Computes the inverse hyperbolic sine of the value [x]. @@ -705,7 +694,7 @@ external public fun tanh(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_asinhf") -external public fun asinh(x: Float): Float +external public actual fun asinh(x: Float): Float /** * Computes the inverse hyperbolic cosine of the value [x]. @@ -719,7 +708,7 @@ external public fun asinh(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_acoshf") -external public fun acosh(x: Float): Float +external public actual fun acosh(x: Float): Float /** * Computes the inverse hyperbolic tangent of the value [x]. @@ -734,7 +723,7 @@ external public fun acosh(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_atanhf") -external public fun atanh(x: Float): Float +external public actual fun atanh(x: Float): Float /** * Computes `sqrt(x^2 + y^2)` without intermediate overflow or underflow. @@ -745,7 +734,7 @@ external public fun atanh(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_hypotf") -external public fun hypot(x: Float, y: Float): Float +external public actual fun hypot(x: Float, y: Float): Float /** * Computes the positive square root of the value [x]. @@ -755,7 +744,7 @@ external public fun hypot(x: Float, y: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_sqrtf") -external public fun sqrt(x: Float): Float +external public actual fun sqrt(x: Float): Float /** * Computes Euler's number `e` raised to the power of the value [x]. @@ -767,23 +756,23 @@ external public fun sqrt(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_expf") -external public fun exp(x: Float): Float +external public actual fun exp(x: Float): Float /** * Computes `exp(x) - 1`. * - * This function can be implemented to produce more precise result for [x] near zero. + * This actual function can be implemented to produce more precise result for [x] near zero. * * Special cases: * - `expm1(NaN)` is `NaN` * - `expm1(+Inf)` is `+Inf` * - `expm1(-Inf)` is `-1.0` * - * @see [exp] function. + * @see [exp] actual function. */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_expm1f") -external public fun expm1(x: Float): Float +external public actual fun expm1(x: Float): Float /** * Computes the logarithm of the value [x] to the given [base]. @@ -795,10 +784,10 @@ external public fun expm1(x: Float): Float * - `log(+Inf, b)` is `+Inf` for `b > 1` and `-Inf` for `b < 1` * - `log(0.0, b)` is `-Inf` for `b > 1` and `+Inf` for `b > 1` * - * See also logarithm functions for common fixed bases: [ln], [log10] and [log2]. + * See also logarithm actual functions for common fixed bases: [ln], [log10] and [log2]. */ @SinceKotlin("1.2") -public fun log(x: Float, base: Float): Float { +public actual fun log(x: Float, base: Float): Float { if (base <= 0.0F || base == 1.0F) return Float.NaN return ln(x) / ln(base) } @@ -814,30 +803,30 @@ public fun log(x: Float, base: Float): Float { */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_lnf") -external public fun ln(x: Float): Float +external public actual fun ln(x: Float): Float /** * Computes the common logarithm (base 10) of the value [x]. * - * @see [ln] function for special cases. + * @see [ln] actual function for special cases. */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_log10f") -external public fun log10(x: Float): Float +external public actual fun log10(x: Float): Float /** * Computes the binary logarithm (base 2) of the value [x]. * - * @see [ln] function for special cases. + * @see [ln] actual function for special cases. */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_log2f") -external public fun log2(x: Float): Float +external public actual fun log2(x: Float): Float /** * Computes `ln(a + 1)`. * - * This function can be implemented to produce more precise result for [x] near zero. + * This actual function can be implemented to produce more precise result for [x] near zero. * * Special cases: * - `ln1p(NaN)` is `NaN` @@ -845,12 +834,12 @@ external public fun log2(x: Float): Float * - `ln1p(-1.0)` is `-Inf` * - `ln1p(+Inf)` is `+Inf` * - * @see [ln] function - * @see [expm1] function + * @see [ln] actual function + * @see [expm1] actual function */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_ln1pf") -external public fun ln1p(x: Float): Float +external public actual fun ln1p(x: Float): Float /** * Rounds the given value [x] to an integer towards positive infinity. @@ -862,7 +851,7 @@ external public fun ln1p(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_ceilf") -external public fun ceil(x: Float): Float +external public actual fun ceil(x: Float): Float /** * Rounds the given value [x] to an integer towards negative infinity. @@ -874,7 +863,7 @@ external public fun ceil(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_floorf") -external public fun floor(x: Float): Float +external public actual fun floor(x: Float): Float /** * Rounds the given value [x] to an integer towards zero. @@ -885,7 +874,7 @@ external public fun floor(x: Float): Float * - `truncate(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. */ @SinceKotlin("1.2") -public fun truncate(x: Float): Float = when { +public actual fun truncate(x: Float): Float = when { x.isNaN() || x.isInfinite() -> x x > 0 -> floor(x) else -> ceil(x) @@ -899,7 +888,7 @@ public fun truncate(x: Float): Float = when { */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_roundf") -external public fun round(x: Float): Float +external public actual fun round(x: Float): Float /** @@ -912,7 +901,7 @@ external public fun round(x: Float): Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_absf") -external public fun abs(x: Float): Float +external public actual fun abs(x: Float): Float /** * Returns the sign of the given value [x]: @@ -924,7 +913,7 @@ external public fun abs(x: Float): Float * - `sign(NaN)` is `NaN` */ @SinceKotlin("1.2") -public fun sign(x: Float): Float = when { +public actual fun sign(x: Float): Float = when { x.isNaN() -> Float.NaN x > 0 -> 1.0f x < 0 -> -1.0f @@ -937,7 +926,7 @@ public fun sign(x: Float): Float = when { * If either value is `NaN`, then the result is `NaN`. */ @SinceKotlin("1.2") -public fun min(a: Float, b: Float): Float = when { +public actual fun min(a: Float, b: Float): Float = when { a.isNaN() || b.isNaN() -> Float.NaN a == 0.0f && b == 0.0f -> if (a.signBit()) a else b // -0.0 < +0.0 else -> if (a < b) a else b @@ -948,7 +937,7 @@ public fun min(a: Float, b: Float): Float = when { * If either value is `NaN`, then the result is `NaN`. */ @SinceKotlin("1.2") -public fun max(a: Float, b: Float): Float = when { +public actual fun max(a: Float, b: Float): Float = when { a.isNaN() || b.isNaN() -> Float.NaN a == 0.0f && b == 0.0f -> if (!a.signBit()) a else b // -0.0 < +0.0 else -> if (a > b) a else b @@ -969,7 +958,7 @@ public fun max(a: Float, b: Float): Float = when { */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_Float_pow") -external public fun Float.pow(x: Float): Float +external public actual fun Float.pow(x: Float): Float /** * Raises this value to the integer power [n]. @@ -977,7 +966,7 @@ external public fun Float.pow(x: Float): Float * See the other overload of [pow] for details. */ @SinceKotlin("1.2") -public fun Float.pow(n: Int): Float = pow(n.toFloat()) +public actual fun Float.pow(n: Int): Float = pow(n.toFloat()) /** * Computes the remainder of division of this value by the [divisor] value according to the IEEE 754 standard. @@ -1001,10 +990,10 @@ external public fun Float.IEEErem(divisor: Float): Float * Special cases: * - `NaN.absoluteValue` is `NaN` * - * @see abs function + * @see abs actual function */ @SinceKotlin("1.2") -public val Float.absoluteValue: Float +public actual val Float.absoluteValue: Float get() = abs(this) /** @@ -1017,7 +1006,7 @@ public val Float.absoluteValue: Float * - `NaN.sign` is `NaN` */ @SinceKotlin("1.2") -public val Float.sign: Float +public actual val Float.sign: Float get() = sign(this) /** @@ -1027,12 +1016,12 @@ public val Float.sign: Float */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_Float_withSign") -external public fun Float.withSign(sign: Float): Float +external public actual fun Float.withSign(sign: Float): Float /** * Returns this value with the sign bit same as of the [sign] value. */ @SinceKotlin("1.2") -public fun Float.withSign(sign: Int): Float = withSign(sign.toFloat()) +public actual fun Float.withSign(sign: Int): Float = withSign(sign.toFloat()) @SinceKotlin("1.2") public val Float.ulp: Float @@ -1088,7 +1077,7 @@ external private fun Float.signBit(): Boolean * @throws IllegalArgumentException when this value is `NaN` */ @SinceKotlin("1.2") -public fun Float.roundToInt(): Int = when { +public actual fun Float.roundToInt(): Int = when { isNaN() -> throw IllegalArgumentException("Cannot round NaN value.") this > Int.MAX_VALUE -> Int.MAX_VALUE this < Int.MIN_VALUE -> Int.MIN_VALUE @@ -1106,7 +1095,7 @@ public fun Float.roundToInt(): Int = when { * @throws IllegalArgumentException when this value is `NaN` */ @SinceKotlin("1.2") -public fun Float.roundToLong(): Long = when { +public actual fun Float.roundToLong(): Long = when { isNaN() -> throw IllegalArgumentException("Cannot round NaN value.") this > Long.MAX_VALUE -> Long.MAX_VALUE this < Long.MIN_VALUE -> Long.MIN_VALUE @@ -1127,19 +1116,19 @@ public fun Float.roundToLong(): Long = when { */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_absi") -external public fun abs(n: Int): Int +external public actual fun abs(n: Int): Int /** * Returns the smaller of two values. */ @SinceKotlin("1.2") -public fun min(a: Int, b: Int): Int = if (a < b) a else b +public actual fun min(a: Int, b: Int): Int = if (a < b) a else b /** * Returns the greater of two values. */ @SinceKotlin("1.2") -public fun max(a: Int, b: Int): Int = if (a > b) a else b +public actual fun max(a: Int, b: Int): Int = if (a > b) a else b /** * Returns the absolute value of this value. @@ -1147,10 +1136,10 @@ public fun max(a: Int, b: Int): Int = if (a > b) a else b * Special cases: * - `Int.MIN_VALUE.absoluteValue` is `Int.MIN_VALUE` due to an overflow * - * @see abs function + * @see abs actual function */ @SinceKotlin("1.2") -public val Int.absoluteValue: Int +public actual val Int.absoluteValue: Int get() = abs(this) /** @@ -1160,7 +1149,7 @@ public val Int.absoluteValue: Int * - `1` if the value is positive */ @SinceKotlin("1.2") -public val Int.sign: Int +public actual val Int.sign: Int get() = when { this < 0 -> -1 this > 0 -> 1 @@ -1178,19 +1167,19 @@ public val Int.sign: Int */ @SinceKotlin("1.2") @SymbolName("Kotlin_math_absl") -external public fun abs(n: Long): Long +external public actual fun abs(n: Long): Long /** * Returns the smaller of two values. */ @SinceKotlin("1.2") -public fun min(a: Long, b: Long): Long = if (a < b) a else b +public actual fun min(a: Long, b: Long): Long = if (a < b) a else b /** * Returns the greater of two values. */ @SinceKotlin("1.2") -public fun max(a: Long, b: Long): Long = if (a > b) a else b +public actual fun max(a: Long, b: Long): Long = if (a > b) a else b /** * Returns the absolute value of this value. @@ -1198,10 +1187,10 @@ public fun max(a: Long, b: Long): Long = if (a > b) a else b * Special cases: * - `Long.MIN_VALUE.absoluteValue` is `Long.MIN_VALUE` due to an overflow * - * @see abs function + * @see abs actual function */ @SinceKotlin("1.2") -public val Long.absoluteValue: Long +public actual val Long.absoluteValue: Long get() = abs(this) /** @@ -1211,7 +1200,7 @@ public val Long.absoluteValue: Long * - `1` if the value is positive */ @SinceKotlin("1.2") -public val Long.sign: Int +public actual val Long.sign: Int get() = when { this < 0 -> -1 this > 0 -> 1 diff --git a/runtime/src/main/kotlin/kotlin/properties/Delegates.kt b/runtime/src/main/kotlin/kotlin/properties/Delegates.kt deleted file mode 100644 index b2bd1e4eb75..00000000000 --- a/runtime/src/main/kotlin/kotlin/properties/Delegates.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.properties - -import kotlin.reflect.KProperty - -/** - * Standard property delegates. - */ -public object Delegates { - /** - * Returns a property delegate for a read/write property with a non-`null` value that is initialized not during - * object construction time but at a later time. Trying to read the property before the initial value has been - * assigned results in an exception. - */ - public fun notNull(): ReadWriteProperty = NotNullVar() - - /** - * Returns a property delegate for a read/write property that calls a specified callback function when changed. - * @param initialValue the initial value of the property. - * @param onChange the callback which is called after the change of the property is made. The value of the property - * has already been changed when this callback is invoked. - */ - public inline fun observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit): - ReadWriteProperty = object : ObservableProperty(initialValue) { - override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue) - } - - /** - * Returns a property delegate for a read/write property that calls a specified callback function when changed, - * allowing the callback to veto the modification. - * @param initialValue the initial value of the property. - * @param onChange the callback which is called before a change to the property value is attempted. - * The value of the property hasn't been changed yet, when this callback is invoked. - * If the callback returns `true` the value of the property is being set to the new value, - * and if the callback returns `false` the new value is discarded and the property remains its old value. - */ - public inline fun vetoable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean): - ReadWriteProperty = object : ObservableProperty(initialValue) { - override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = onChange(property, oldValue, newValue) - } - -} - - -private class NotNullVar() : ReadWriteProperty { - private var value: T? = null - - public override fun getValue(thisRef: Any?, property: KProperty<*>): T { - return value ?: throw IllegalStateException("Property ${property.name} should be initialized before get.") - } - - public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { - this.value = value - } -} - diff --git a/runtime/src/main/kotlin/kotlin/properties/Interfaces.kt b/runtime/src/main/kotlin/kotlin/properties/Interfaces.kt deleted file mode 100644 index 39faf05290d..00000000000 --- a/runtime/src/main/kotlin/kotlin/properties/Interfaces.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.properties - -import kotlin.reflect.KProperty - -/** - * Base interface that can be used for implementing property delegates of read-only properties. - * - * This is provided only for convenience; you don't have to extend this interface - * as long as your property delegate has methods with the same signatures. - * - * @param R the type of object which owns the delegated property. - * @param T the type of the property value. - */ -public interface ReadOnlyProperty { - /** - * Returns the value of the property for the given object. - * @param thisRef the object for which the value is requested. - * @param property the metadata for the property. - * @return the property value. - */ - public operator fun getValue(thisRef: R, property: KProperty<*>): T -} - -/** - * Base interface that can be used for implementing property delegates of read-write properties. - * - * This is provided only for convenience; you don't have to extend this interface - * as long as your property delegate has methods with the same signatures. - * - * @param R the type of object which owns the delegated property. - * @param T the type of the property value. - */ -public interface ReadWriteProperty { - /** - * Returns the value of the property for the given object. - * @param thisRef the object for which the value is requested. - * @param property the metadata for the property. - * @return the property value. - */ - public operator fun getValue(thisRef: R, property: KProperty<*>): T - - /** - * Sets the value of the property for the given object. - * @param thisRef the object for which the value is requested. - * @param property the metadata for the property. - * @param value the value to set. - */ - public operator fun setValue(thisRef: R, property: KProperty<*>, value: T) -} diff --git a/runtime/src/main/kotlin/kotlin/properties/ObservableProperty.kt b/runtime/src/main/kotlin/kotlin/properties/ObservableProperty.kt deleted file mode 100644 index 1b52ba64e1e..00000000000 --- a/runtime/src/main/kotlin/kotlin/properties/ObservableProperty.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.properties - -import kotlin.reflect.KProperty - -/** - * Implements the core logic of a property delegate for a read/write property that calls callback functions when changed. - * @param initialValue the initial value of the property. - */ -public abstract class ObservableProperty(initialValue: T) : ReadWriteProperty { - private var value = initialValue - - /** - * The callback which is called before a change to the property value is attempted. - * The value of the property hasn't been changed yet, when this callback is invoked. - * If the callback returns `true` the value of the property is being set to the new value, - * and if the callback returns `false` the new value is discarded and the property remains its old value. - */ - protected open fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = true - - /** - * The callback which is called after the change of the property is made. The value of the property - * has already been changed when this callback is invoked. - */ - protected open fun afterChange (property: KProperty<*>, oldValue: T, newValue: T): Unit {} - - public override fun getValue(thisRef: Any?, property: KProperty<*>): T { - return value - } - - public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { - val oldValue = this.value - if (!beforeChange(property, oldValue, value)) { - return - } - this.value = value - afterChange(property, oldValue, value) - } -} \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/ranges/Ranges.kt b/runtime/src/main/kotlin/kotlin/ranges/Ranges.kt index 4f43689a8d9..40d8ccebe70 100644 --- a/runtime/src/main/kotlin/kotlin/ranges/Ranges.kt +++ b/runtime/src/main/kotlin/kotlin/ranges/Ranges.kt @@ -94,473 +94,6 @@ public class LongRange(start: Long, endInclusive: Long) : LongProgression(start, } } -/** - * Ensures that this value is not less than the specified [minimumValue]. - * - * @return this value if it's greater than or equal to the [minimumValue] or the -[minimumValue] otherwise. - */ -public fun > T.coerceAtLeast(minimumValue: T): T { - return if (this < minimumValue) minimumValue else this -} - -/** - * Ensures that this value is not less than the specified [minimumValue]. - * - * @return this value if it's greater than or equal to the [minimumValue] or the [minimumValue] otherwise. - */ -public fun Byte.coerceAtLeast(minimumValue: Byte): Byte { - return if (this < minimumValue) minimumValue else this -} - -/** - * Ensures that this value is not less than the specified [minimumValue]. - * - * @return this value if it's greater than or equal to the [minimumValue] or the [minimumValue] otherwise. - */ -public fun Short.coerceAtLeast(minimumValue: Short): Short { - return if (this < minimumValue) minimumValue else this -} - -/** - * Ensures that this value is not less than the specified [minimumValue]. - * - * @return this value if it's greater than or equal to the [minimumValue] or the [minimumValue] otherwise. - */ -public fun Int.coerceAtLeast(minimumValue: Int): Int { - return if (this < minimumValue) minimumValue else this -} - -/** - * Ensures that this value is not less than the specified [minimumValue]. - * - * @return this value if it's greater than or equal to the [minimumValue] or the [minimumValue] otherwise. - */ -public fun Long.coerceAtLeast(minimumValue: Long): Long { - return if (this < minimumValue) minimumValue else this -} - -/** - * Ensures that this value is not less than the specified [minimumValue]. - * - * @return this value if it's greater than or equal to the [minimumValue] or the [minimumValue] otherwise. - */ -public fun Float.coerceAtLeast(minimumValue: Float): Float { - return if (this < minimumValue) minimumValue else this -} - -/** - * Ensures that this value is not less than the specified [minimumValue]. - * - * @return this value if it's greater than or equal to the [minimumValue] or the [minimumValue] otherwise. - */ -public fun Double.coerceAtLeast(minimumValue: Double): Double { - return if (this < minimumValue) minimumValue else this -} - -/** - * Ensures that this value is not greater than the specified [maximumValue]. - * - * @return this value if it's less than or equal to the [maximumValue] or the [maximumValue] otherwise. - */ -public fun > T.coerceAtMost(maximumValue: T): T { - return if (this > maximumValue) maximumValue else this -} - -/** - * Ensures that this value is not greater than the specified [maximumValue]. - * - * @return this value if it's less than or equal to the [maximumValue] or the [maximumValue] otherwise. - */ -public fun Byte.coerceAtMost(maximumValue: Byte): Byte { - return if (this > maximumValue) maximumValue else this -} - -/** - * Ensures that this value is not greater than the specified [maximumValue]. - * - * @return this value if it's less than or equal to the [maximumValue] or the [maximumValue] otherwise. - */ -public fun Short.coerceAtMost(maximumValue: Short): Short { - return if (this > maximumValue) maximumValue else this -} - -/** - * Ensures that this value is not greater than the specified [maximumValue]. - * - * @return this value if it's less than or equal to the [maximumValue] or the [maximumValue] otherwise. - */ -public fun Int.coerceAtMost(maximumValue: Int): Int { - return if (this > maximumValue) maximumValue else this -} - -/** - * Ensures that this value is not greater than the specified [maximumValue]. - * - * @return this value if it's less than or equal to the [maximumValue] or the [maximumValue] otherwise. - */ -public fun Long.coerceAtMost(maximumValue: Long): Long { - return if (this > maximumValue) maximumValue else this -} - -/** - * Ensures that this value is not greater than the specified [maximumValue]. - * - * @return this value if it's less than or equal to the [maximumValue] or the [maximumValue] otherwise. - */ -public fun Float.coerceAtMost(maximumValue: Float): Float { - return if (this > maximumValue) maximumValue else this -} - -/** - * Ensures that this value is not greater than the specified [maximumValue]. - * - * @return this value if it's less than or equal to the [maximumValue] or the [maximumValue] otherwise. - */ -public fun Double.coerceAtMost(maximumValue: Double): Double { - return if (this > maximumValue) maximumValue else this -} - -/** - * Ensures that this value lies in the specified range [minimumValue]..[maximumValue]. - * - * @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue]. - */ -public fun > T.coerceIn(minimumValue: T?, maximumValue: T?): T { - if (minimumValue !== null && maximumValue !== null) { - if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.") - if (this < minimumValue) return minimumValue - if (this > maximumValue) return maximumValue - } - else { - if (minimumValue !== null && this < minimumValue) return minimumValue - if (maximumValue !== null && this > maximumValue) return maximumValue - } - return this -} - -/** - * Ensures that this value lies in the specified range [minimumValue]..[maximumValue]. - * - * @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue]. - */ -public fun Byte.coerceIn(minimumValue: Byte, maximumValue: Byte): Byte { - if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.") - if (this < minimumValue) return minimumValue - if (this > maximumValue) return maximumValue - return this -} - -/** - * Ensures that this value lies in the specified range [minimumValue]..[maximumValue]. - * - * @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue]. - */ -public fun Short.coerceIn(minimumValue: Short, maximumValue: Short): Short { - if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.") - if (this < minimumValue) return minimumValue - if (this > maximumValue) return maximumValue - return this -} - -/** - * Ensures that this value lies in the specified range [minimumValue]..[maximumValue]. - * - * @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue]. - */ -public fun Int.coerceIn(minimumValue: Int, maximumValue: Int): Int { - if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.") - if (this < minimumValue) return minimumValue - if (this > maximumValue) return maximumValue - return this -} - -/** - * Ensures that this value lies in the specified range [minimumValue]..[maximumValue]. - * - * @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue]. - */ -public fun Long.coerceIn(minimumValue: Long, maximumValue: Long): Long { - if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.") - if (this < minimumValue) return minimumValue - if (this > maximumValue) return maximumValue - return this -} - -/** - * Ensures that this value lies in the specified range [minimumValue]..[maximumValue]. - * - * @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue]. - */ -public fun Float.coerceIn(minimumValue: Float, maximumValue: Float): Float { - if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.") - if (this < minimumValue) return minimumValue - if (this > maximumValue) return maximumValue - return this -} - -/** - * Ensures that this value lies in the specified range [minimumValue]..[maximumValue]. - * - * @return this value if it's in the range, or [minimumValue] if this value is less than [minimumValue], or [maximumValue] if this value is greater than [maximumValue]. - */ -public fun Double.coerceIn(minimumValue: Double, maximumValue: Double): Double { - if (minimumValue > maximumValue) throw IllegalArgumentException("Cannot coerce value to an empty range: maximum $maximumValue is less than minimum $minimumValue.") - if (this < minimumValue) return minimumValue - if (this > maximumValue) return maximumValue - return this -} - -/** - * Ensures that this value lies in the specified [range]. - * - * @return this value if it's in the [range], or range.start if this value is less than range.start, or range.end if this value is greater than range.end. - */ -public fun > T.coerceIn(range: ClosedRange): T { - if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.") - return if (this < range.start) range.start else if (this > range.endInclusive) range.endInclusive else this -} - -/** - * Ensures that this value lies in the specified [range]. - * - * @return this value if it's in the [range], or range.start if this value is less than range.start, or range.end if this value is greater than range.end. - */ -public fun Int.coerceIn(range: ClosedRange): Int { - if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.") - return if (this < range.start) range.start else if (this > range.endInclusive) range.endInclusive else this -} - -/** - * Ensures that this value lies in the specified [range]. - * - * @return this value if it's in the [range], or range.start if this value is less than range.start, or range.end if this value is greater than range.end. - */ -public fun Long.coerceIn(range: ClosedRange): Long { - if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.") - return if (this < range.start) range.start else if (this > range.endInclusive) range.endInclusive else this -} - - -internal fun checkStepIsPositive(isPositive: Boolean, step: Number) { - if (!isPositive) throw IllegalArgumentException("Step must be positive, was: $step.") -} - -// This part is from generated _Ranges.kt. -/** - * Returns a progression that goes over the same range in the opposite direction with the same step. - */ -public fun IntProgression.reversed() = IntProgression.fromClosedRange(last, first, -step) - -/** - * Returns a progression that goes over the same range with the given step. - */ -public infix fun IntProgression.step(step: Int): IntProgression { - checkStepIsPositive(step > 0, step) - return IntProgression.fromClosedRange(first, last, if (this.step > 0) step else -step) -} - -/** - * Returns a progression that goes over the same range with the given step. - */ -public infix fun LongProgression.step(step: Long): LongProgression { - checkStepIsPositive(step > 0, step) - return LongProgression.fromClosedRange(first, last, if (this.step > 0) step else -step) -} - -/** - * Returns a progression that goes over the same range with the given step. - */ -public infix fun CharProgression.step(step: Int): CharProgression { - checkStepIsPositive(step > 0, step) - return CharProgression.fromClosedRange(first, last, if (this.step > 0) step else -step) -} - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Int.downTo(to: Byte) = IntProgression.fromClosedRange(this, to.toInt(), -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Long.downTo(to: Byte) = LongProgression.fromClosedRange(this, to.toLong(), -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Byte.downTo(to: Byte): IntProgression = - IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Short.downTo(to: Byte) = - IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Char.downTo(to: Char): CharProgression = CharProgression.fromClosedRange(this, to, -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Int.downTo(to: Int) = IntProgression.fromClosedRange(this, to, -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Long.downTo(to: Int) = LongProgression.fromClosedRange(this, to.toLong(), -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Byte.downTo(to: Int): IntProgression = - IntProgression.fromClosedRange(this.toInt(), to, -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Short.downTo(to: Int) = IntProgression.fromClosedRange(this.toInt(), to, -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Int.downTo(to: Long) = LongProgression.fromClosedRange(this.toLong(), to, -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Long.downTo(to: Long) = LongProgression.fromClosedRange(this, to, -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Byte.downTo(to: Long): LongProgression = - LongProgression.fromClosedRange(this.toLong(), to, -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Int.downTo(to: Short) = IntProgression.fromClosedRange(this, to.toInt(), -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Long.downTo(to: Short) = LongProgression.fromClosedRange(this, to.toLong(), -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Byte.downTo(to: Short): IntProgression = - IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1) - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Short.downTo(to: Short): IntProgression = - IntProgression.fromClosedRange(this.toInt(), to.toInt(), -1) - -/** - * Represents a range of floating point numbers. - * Extends [ClosedRange] interface providing custom operation [lessThanOrEquals] for comparing values of range domain type. - * - * This interface is implemented by floating point ranges returned by [Float.rangeTo] and [Double.rangeTo] operators to - * achieve IEEE-754 comparison order instead of total order of floating point numbers. - */ -public interface ClosedFloatingPointRange> : ClosedRange { - override fun contains(value: T): Boolean = lessThanOrEquals(start, value) && lessThanOrEquals(value, endInclusive) - override fun isEmpty(): Boolean = !lessThanOrEquals(start, endInclusive) - - /** - * Compares two values of range domain type and returns true if first is less than or equal to second. - */ - fun lessThanOrEquals(a: T, b: T): Boolean -} - -/** - * Represents a range of [Comparable] values. - */ -private open class ComparableRange> ( - override val start: T, - override val endInclusive: T -): ClosedRange { - - override fun equals(other: Any?): Boolean { - return other is ComparableRange<*> && (isEmpty() && other.isEmpty() || - start == other.start && endInclusive == other.endInclusive) - } - - override fun hashCode(): Int { - return if (isEmpty()) -1 else 31 * start.hashCode() + endInclusive.hashCode() - } - - override fun toString(): String = "$start..$endInclusive" -} - -/** - * A closed range of values of type `Double`. - * - * Numbers are compared with the ends of this range according to IEEE-754. - */ -private class ClosedDoubleRange ( - start: Double, - endInclusive: Double -) : ClosedFloatingPointRange { - private val _start = start - private val _endInclusive = endInclusive - override val start: Double get() = _start - override val endInclusive: Double get() = _endInclusive - - override fun lessThanOrEquals(a: Double, b: Double): Boolean = a <= b - - override fun contains(value: Double): Boolean = value >= _start && value <= _endInclusive - override fun isEmpty(): Boolean = !(_start <= _endInclusive) - - override fun equals(other: Any?): Boolean { - return other is ClosedDoubleRange && (isEmpty() && other.isEmpty() || - _start == other._start && _endInclusive == other._endInclusive) - } - - override fun hashCode(): Int { - return if (isEmpty()) -1 else 31 * _start.hashCode() + _endInclusive.hashCode() - } - override fun toString(): String = "$_start..$_endInclusive" -} - /** * A closed range of values of type `Float`. * @@ -591,20 +124,6 @@ private class ClosedFloatRange ( override fun toString(): String = "$_start..$_endInclusive" } -/** - * Creates a range from this [Comparable] value to the specified [that] value. - * - * This value needs to be smaller than [that] value, otherwise the returned range will be empty. - */ -public operator fun > T.rangeTo(that: T): ClosedRange = ComparableRange(this, that) - -/** - * Creates a range from this [Double] value to the specified [other] value. - * - * Numbers are compared with the ends of this range according to IEEE-754. - */ -public operator fun Double.rangeTo(that: Double): ClosedFloatingPointRange = ClosedDoubleRange(this, that) - /** * Creates a range from this [Float] value to the specified [other] value. * diff --git a/runtime/src/main/kotlin/kotlin/ranges/_Ranges.kt b/runtime/src/main/kotlin/kotlin/ranges/_Ranges.kt deleted file mode 100644 index aaa9ac1bdee..00000000000 --- a/runtime/src/main/kotlin/kotlin/ranges/_Ranges.kt +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.ranges - -/** - * Returns a range from this value up to but excluding the specified [to] value. - */ -public infix fun Int.until(to: Byte): IntRange { - return this .. (to.toInt() - 1).toInt() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - */ -public infix fun Long.until(to: Byte): LongRange { - return this .. (to.toLong() - 1).toLong() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - */ -public infix fun Byte.until(to: Byte): IntRange { - return this.toInt() .. (to.toInt() - 1).toInt() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - */ -public infix fun Short.until(to: Byte): IntRange { - return this.toInt() .. (to.toInt() - 1).toInt() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - * - * If the [to] value is less than or equal to ['\u0000'] the returned range is empty. - */ -public infix fun Char.until(to: Char): CharRange { - if (to <= '\u0000') return CharRange.EMPTY - return this .. (to - 1).toChar() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - * - * If the [to] value is less than or equal to [Int.MIN_VALUE] the returned range is empty. - */ -public infix fun Int.until(to: Int): IntRange { - if (to <= Int.MIN_VALUE) return IntRange.EMPTY - return this .. (to - 1).toInt() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - */ -public infix fun Long.until(to: Int): LongRange { - return this .. (to.toLong() - 1).toLong() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - * - * If the [to] value is less than or equal to [Int.MIN_VALUE] the returned range is empty. - */ -public infix fun Byte.until(to: Int): IntRange { - if (to <= Int.MIN_VALUE) return IntRange.EMPTY - return this.toInt() .. (to - 1).toInt() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - * - * If the [to] value is less than or equal to [Int.MIN_VALUE] the returned range is empty. - */ -public infix fun Short.until(to: Int): IntRange { - if (to <= Int.MIN_VALUE) return IntRange.EMPTY - return this.toInt() .. (to - 1).toInt() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - * - * If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty. - */ -public infix fun Int.until(to: Long): LongRange { - if (to <= Long.MIN_VALUE) return LongRange.EMPTY - return this.toLong() .. (to - 1).toLong() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - * - * If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty. - */ -public infix fun Long.until(to: Long): LongRange { - if (to <= Long.MIN_VALUE) return LongRange.EMPTY - return this .. (to - 1).toLong() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - * - * If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty. - */ -public infix fun Byte.until(to: Long): LongRange { - if (to <= Long.MIN_VALUE) return LongRange.EMPTY - return this.toLong() .. (to - 1).toLong() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - * - * If the [to] value is less than or equal to [Long.MIN_VALUE] the returned range is empty. - */ -public infix fun Short.until(to: Long): LongRange { - if (to <= Long.MIN_VALUE) return LongRange.EMPTY - return this.toLong() .. (to - 1).toLong() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - */ -public infix fun Int.until(to: Short): IntRange { - return this .. (to.toInt() - 1).toInt() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - */ -public infix fun Long.until(to: Short): LongRange { - return this .. (to.toLong() - 1).toLong() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - */ -public infix fun Byte.until(to: Short): IntRange { - return this.toInt() .. (to.toInt() - 1).toInt() -} - -/** - * Returns a range from this value up to but excluding the specified [to] value. - */ -public infix fun Short.until(to: Short): IntRange { - return this.toInt() .. (to.toInt() - 1).toInt() -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Byte): Boolean { - return contains(value.toInt()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Byte): Boolean { - return contains(value.toLong()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Byte): Boolean { - return contains(value.toShort()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Byte): Boolean { - return contains(value.toDouble()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Byte): Boolean { - return contains(value.toFloat()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Double): Boolean { - return value.toIntExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Double): Boolean { - return value.toLongExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Double): Boolean { - return value.toByteExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Double): Boolean { - return value.toShortExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Double): Boolean { - return contains(value.toFloat()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Float): Boolean { - return value.toIntExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Float): Boolean { - return value.toLongExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Float): Boolean { - return value.toByteExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Float): Boolean { - return value.toShortExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Float): Boolean { - return contains(value.toDouble()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Int): Boolean { - return contains(value.toLong()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Int): Boolean { - return value.toByteExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Int): Boolean { - return value.toShortExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Int): Boolean { - return contains(value.toDouble()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Int): Boolean { - return contains(value.toFloat()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Long): Boolean { - return value.toIntExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Long): Boolean { - return value.toByteExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Long): Boolean { - return value.toShortExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Long): Boolean { - return contains(value.toDouble()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Long): Boolean { - return contains(value.toFloat()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Short): Boolean { - return contains(value.toInt()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Short): Boolean { - return contains(value.toLong()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Short): Boolean { - return value.toByteExactOrNull().let { if (it != null) contains(it) else false } -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Short): Boolean { - return contains(value.toDouble()) -} - -/** - * Checks if the specified [value] belongs to this range. - */ -public operator fun ClosedRange.contains(value: Short): Boolean { - return contains(value.toFloat()) -} - -/** - * Returns a progression from this value down to the specified [to] value with the step -1. - * - * The [to] value has to be less than this value. - */ -public infix fun Short.downTo(to: Long): LongProgression { - return LongProgression.fromClosedRange(this.toLong(), to, -1L) -} - -/** - * Returns a progression that goes over the same range in the opposite direction with the same step. - */ -public fun LongProgression.reversed(): LongProgression { - return LongProgression.fromClosedRange(last, first, -step) -} - -/** - * Returns a progression that goes over the same range in the opposite direction with the same step. - */ -public fun CharProgression.reversed(): CharProgression { - return CharProgression.fromClosedRange(last, first, -step) -} - -internal fun Int.toByteExactOrNull(): Byte? { - return if (this in Byte.MIN_VALUE.toInt()..Byte.MAX_VALUE.toInt()) this.toByte() else null -} - -internal fun Long.toByteExactOrNull(): Byte? { - return if (this in Byte.MIN_VALUE.toLong()..Byte.MAX_VALUE.toLong()) this.toByte() else null -} - -internal fun Short.toByteExactOrNull(): Byte? { - return if (this in Byte.MIN_VALUE.toShort()..Byte.MAX_VALUE.toShort()) this.toByte() else null -} - -internal fun Double.toByteExactOrNull(): Byte? { - return if (this in Byte.MIN_VALUE.toDouble()..Byte.MAX_VALUE.toDouble()) this.toByte() else null -} - -internal fun Float.toByteExactOrNull(): Byte? { - return if (this in Byte.MIN_VALUE.toFloat()..Byte.MAX_VALUE.toFloat()) this.toByte() else null -} - -internal fun Long.toIntExactOrNull(): Int? { - return if (this in Int.MIN_VALUE.toLong()..Int.MAX_VALUE.toLong()) this.toInt() else null -} - -internal fun Double.toIntExactOrNull(): Int? { - return if (this in Int.MIN_VALUE.toDouble()..Int.MAX_VALUE.toDouble()) this.toInt() else null -} - -internal fun Float.toIntExactOrNull(): Int? { - return if (this in Int.MIN_VALUE.toFloat()..Int.MAX_VALUE.toFloat()) this.toInt() else null -} - -internal fun Double.toLongExactOrNull(): Long? { - return if (this in Long.MIN_VALUE.toDouble()..Long.MAX_VALUE.toDouble()) this.toLong() else null -} - -internal fun Float.toLongExactOrNull(): Long? { - return if (this in Long.MIN_VALUE.toFloat()..Long.MAX_VALUE.toFloat()) this.toLong() else null -} - -internal fun Int.toShortExactOrNull(): Short? { - return if (this in Short.MIN_VALUE.toInt()..Short.MAX_VALUE.toInt()) this.toShort() else null -} - -internal fun Long.toShortExactOrNull(): Short? { - return if (this in Short.MIN_VALUE.toLong()..Short.MAX_VALUE.toLong()) this.toShort() else null -} - -internal fun Double.toShortExactOrNull(): Short? { - return if (this in Short.MIN_VALUE.toDouble()..Short.MAX_VALUE.toDouble()) this.toShort() else null -} - -internal fun Float.toShortExactOrNull(): Short? { - return if (this in Short.MIN_VALUE.toFloat()..Short.MAX_VALUE.toFloat()) this.toShort() else null -} - -/** - * Ensures that this value lies in the specified [range]. - * - * @return this value if it's in the [range], or `range.start` if this value is less than `range.start`, or `range.endInclusive` if this value is greater than `range.endInclusive`. - */ -public fun > T.coerceIn(range: ClosedFloatingPointRange): T { - if (range.isEmpty()) throw IllegalArgumentException("Cannot coerce value to an empty range: $range.") - return when { - // this < start equiv to this <= start && !(this >= start) - range.lessThanOrEquals(this, range.start) && !range.lessThanOrEquals(range.start, this) -> range.start - // this > end equiv to this >= end && !(this <= end) - range.lessThanOrEquals(range.endInclusive, this) && !range.lessThanOrEquals(this, range.endInclusive) -> range.endInclusive - else -> this - } -} diff --git a/runtime/src/main/kotlin/kotlin/sequences/Sequence.kt b/runtime/src/main/kotlin/kotlin/sequences/Sequence.kt deleted file mode 100644 index 88f38a25e9f..00000000000 --- a/runtime/src/main/kotlin/kotlin/sequences/Sequence.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.sequences - -/** - * A sequence that returns values through its iterator. The values are evaluated lazily, and the sequence - * is potentially infinite. - * - * Sequences can be iterated multiple times, however some sequence implementations might constrain themselves - * to be iterated only once. That is mentioned specifically in their documentation (e.g. [generateSequence] overload). - * The latter sequences throw an exception on an attempt to iterate them the second time. - * - * Sequence operations, like [Sequence.map], [Sequence.filter] etc, generally preserve that property of a sequence, and - * again it's documented for an operation if it doesn't. - * - * @param T the type of elements in the sequence. - */ -public interface Sequence { - /** - * Returns an [Iterator] that returns the values from the sequence. - * - * Throws an exception if the sequence is constrained to be iterated once and `iterator` is invoked the second time. - */ - public operator fun iterator(): Iterator -} \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/sequences/Sequences.kt b/runtime/src/main/kotlin/kotlin/sequences/Sequences.kt index 53dfb13b8d9..10875d9e5f9 100644 --- a/runtime/src/main/kotlin/kotlin/sequences/Sequences.kt +++ b/runtime/src/main/kotlin/kotlin/sequences/Sequences.kt @@ -19,2159 +19,15 @@ package kotlin.sequences import kotlin.comparisons.* import kotlin.coroutines.experimental.* - -/** - * Given an [iterator] function constructs a [Sequence] that returns values through the [Iterator] - * provided by that function. - * The values are evaluated lazily, and the sequence is potentially infinite. - * - * @sample samples.collections.Sequences.Building.sequenceFromIterator - */ -@kotlin.internal.InlineOnly -public inline fun Sequence(crossinline iterator: () -> Iterator): Sequence = object : Sequence { - override fun iterator(): Iterator = iterator() -} - -/** - * Creates a sequence that returns all values from this enumeration. The sequence is constrained to be iterated only once. - */ -@FixmeSequences -@kotlin.internal.InlineOnly -public inline fun> T.asSequence(): Sequence = TODO() // this.values().iterator().asSequence() - -/** - * Creates a sequence that returns all elements from this iterator. The sequence is constrained to be iterated only once. - * - * @sample samples.collections.Sequences.Building.sequenceFromIterator - */ -public fun Iterator.asSequence(): Sequence = Sequence { this }.constrainOnce() - -/** - * Creates a sequence that returns the specified values. - * - * @sample samples.collections.Sequences.Building.sequenceOfValues - */ -public fun sequenceOf(vararg elements: T): Sequence = if (elements.isEmpty()) emptySequence() else elements.asSequence() - -/** - * Returns an empty sequence. - */ -public fun emptySequence(): Sequence = EmptySequence - -private object EmptySequence : Sequence, DropTakeSequence { - override fun iterator(): Iterator = EmptyIterator - override fun drop(n: Int) = EmptySequence - override fun take(n: Int) = EmptySequence -} - -/** - * Returns a sequence of all elements from all sequences in this sequence. - */ -public fun Sequence>.flatten(): Sequence = flatten { it.iterator() } - -/** - * Returns a sequence of all elements from all iterables in this sequence. - */ -public fun Sequence>.flatten(): Sequence = flatten { it.iterator() } - -private fun Sequence.flatten(iterator: (T) -> Iterator): Sequence { - if (this is TransformingSequence<*, *>) { - return (this as TransformingSequence<*, T>).flatten(iterator) - } - return FlatteningSequence(this, { it }, iterator) -} - -/** - * Returns a pair of lists, where - * *first* list is built from the first values of each pair from this sequence, - * *second* list is built from the second values of each pair from this sequence. - */ -public fun Sequence>.unzip(): Pair, List> { - val listT = ArrayList() - val listR = ArrayList() - for (pair in this) { - listT.add(pair.first) - listR.add(pair.second) - } - return listT to listR -} - -/** - * A sequence that returns the values from the underlying [sequence] that either match or do not match - * the specified [predicate]. - * - * @param sendWhen If `true`, values for which the predicate returns `true` are returned. Otherwise, - * values for which the predicate returns `false` are returned - */ -internal class FilteringSequence(private val sequence: Sequence, - private val sendWhen: Boolean = true, - private val predicate: (T) -> Boolean -) : Sequence { - - override fun iterator(): Iterator = object : Iterator { - val iterator = sequence.iterator() - var nextState: Int = -1 // -1 for unknown, 0 for done, 1 for continue - var nextItem: T? = null - - private fun calcNext() { - while (iterator.hasNext()) { - val item = iterator.next() - if (predicate(item) == sendWhen) { - nextItem = item - nextState = 1 - return - } - } - nextState = 0 - } - - override fun next(): T { - if (nextState == -1) - calcNext() - if (nextState == 0) - throw NoSuchElementException() - val result = nextItem - nextItem = null - nextState = -1 - @Suppress("UNCHECKED_CAST") - return result as T - } - - override fun hasNext(): Boolean { - if (nextState == -1) - calcNext() - return nextState == 1 - } - } -} - -/** - * A sequence which returns the results of applying the given [transformer] function to the values - * in the underlying [sequence]. - */ - -internal class TransformingSequence -constructor(private val sequence: Sequence, private val transformer: (T) -> R) : Sequence { - override fun iterator(): Iterator = object : Iterator { - val iterator = sequence.iterator() - override fun next(): R { - return transformer(iterator.next()) - } - - override fun hasNext(): Boolean { - return iterator.hasNext() - } - } - - internal fun flatten(iterator: (R) -> Iterator): Sequence { - return FlatteningSequence(sequence, transformer, iterator) - } -} - -/** - * A sequence which returns the results of applying the given [transformer] function to the values - * in the underlying [sequence], where the transformer function takes the index of the value in the underlying - * sequence along with the value itself. - */ -internal class TransformingIndexedSequence -constructor(private val sequence: Sequence, private val transformer: (Int, T) -> R) : Sequence { - override fun iterator(): Iterator = object : Iterator { - val iterator = sequence.iterator() - var index = 0 - override fun next(): R { - return transformer(index++, iterator.next()) - } - - override fun hasNext(): Boolean { - return iterator.hasNext() - } - } -} - -/** - * A sequence which combines values from the underlying [sequence] with their indices and returns them as - * [IndexedValue] objects. - */ -internal class IndexingSequence -constructor(private val sequence: Sequence) : Sequence> { - override fun iterator(): Iterator> = object : Iterator> { - val iterator = sequence.iterator() - var index = 0 - override fun next(): IndexedValue { - return IndexedValue(index++, iterator.next()) - } - - override fun hasNext(): Boolean { - return iterator.hasNext() - } - } -} - -/** - * A sequence which takes the values from two parallel underlying sequences, passes them to the given - * [transform] function and returns the values returned by that function. The sequence stops returning - * values as soon as one of the underlying sequences stops returning values. - */ -internal class MergingSequence -constructor(private val sequence1: Sequence, - private val sequence2: Sequence, - private val transform: (T1, T2) -> V -) : Sequence { - override fun iterator(): Iterator = object : Iterator { - val iterator1 = sequence1.iterator() - val iterator2 = sequence2.iterator() - override fun next(): V { - return transform(iterator1.next(), iterator2.next()) - } - - override fun hasNext(): Boolean { - return iterator1.hasNext() && iterator2.hasNext() - } - } -} - -internal class FlatteningSequence -constructor( - private val sequence: Sequence, - private val transformer: (T) -> R, - private val iterator: (R) -> Iterator -) : Sequence { - override fun iterator(): Iterator = object : Iterator { - val iterator = sequence.iterator() - var itemIterator: Iterator? = null - - override fun next(): E { - if (!ensureItemIterator()) - throw NoSuchElementException() - return itemIterator!!.next() - } - - override fun hasNext(): Boolean { - return ensureItemIterator() - } - - private fun ensureItemIterator(): Boolean { - if (itemIterator?.hasNext() == false) - itemIterator = null - - while (itemIterator == null) { - if (!iterator.hasNext()) { - return false - } else { - val element = iterator.next() - val nextItemIterator = iterator(transformer(element)) - if (nextItemIterator.hasNext()) { - itemIterator = nextItemIterator - return true - } - } - } - return true - } - } -} - -/** - * A sequence that supports drop(n) and take(n) operations - */ -internal interface DropTakeSequence : Sequence { - fun drop(n: Int): Sequence - fun take(n: Int): Sequence -} - -/** - * A sequence that skips [startIndex] values from the underlying [sequence] - * and stops returning values right before [endIndex], i.e. stops at `endIndex - 1` - */ -internal class SubSequence ( - private val sequence: Sequence, - private val startIndex: Int, - private val endIndex: Int -): Sequence, DropTakeSequence { - - init { - require(startIndex >= 0) { "startIndex should be non-negative, but is $startIndex" } - require(endIndex >= 0) { "endIndex should be non-negative, but is $endIndex" } - require(endIndex >= startIndex) { "endIndex should be not less than startIndex, but was $endIndex < $startIndex"} - } - - private val count: Int get() = endIndex - startIndex - override fun drop(n: Int): Sequence = if (n >= count) emptySequence() else SubSequence(sequence, startIndex + n, endIndex) - override fun take(n: Int): Sequence = if (n >= count) this else SubSequence(sequence, startIndex, startIndex + n) - - override fun iterator() = object : Iterator { - - val iterator = sequence.iterator() - var position = 0 - - // Shouldn't be called from constructor to avoid premature iteration - private fun drop() { - while(position < startIndex && iterator.hasNext()) { - iterator.next() - position++ - } - } - - override fun hasNext(): Boolean { - drop() - return (position < endIndex) && iterator.hasNext() - } - - override fun next(): T { - drop() - if (position >= endIndex) - throw NoSuchElementException() - position++ - return iterator.next() - } - } -} - -/** - * A sequence that returns at most [count] values from the underlying [sequence], and stops returning values - * as soon as that count is reached. - */ -internal class TakeSequence ( - private val sequence: Sequence, - private val count: Int -) : Sequence, DropTakeSequence { - - init { - require (count >= 0) { "count must be non-negative, but was $count." } - } - - override fun drop(n: Int): Sequence = if (n >= count) emptySequence() else SubSequence(sequence, n, count) - override fun take(n: Int): Sequence = if (n >= count) this else TakeSequence(sequence, n) - - override fun iterator(): Iterator = object : Iterator { - var left = count - val iterator = sequence.iterator() - - override fun next(): T { - if (left == 0) - throw NoSuchElementException() - left-- - return iterator.next() - } - - override fun hasNext(): Boolean { - return left > 0 && iterator.hasNext() - } - } -} - -/** - * A sequence that returns values from the underlying [sequence] while the [predicate] function returns - * `true`, and stops returning values once the function returns `false` for the next element. - */ -internal class TakeWhileSequence -constructor(private val sequence: Sequence, - private val predicate: (T) -> Boolean -) : Sequence { - override fun iterator(): Iterator = object : Iterator { - val iterator = sequence.iterator() - var nextState: Int = -1 // -1 for unknown, 0 for done, 1 for continue - var nextItem: T? = null - - private fun calcNext() { - if (iterator.hasNext()) { - val item = iterator.next() - if (predicate(item)) { - nextState = 1 - nextItem = item - return - } - } - nextState = 0 - } - - override fun next(): T { - if (nextState == -1) - calcNext() // will change nextState - if (nextState == 0) - throw NoSuchElementException() - @Suppress("UNCHECKED_CAST") - val result = nextItem as T - - // Clean next to avoid keeping reference on yielded instance - nextItem = null - nextState = -1 - return result - } - - override fun hasNext(): Boolean { - if (nextState == -1) - calcNext() // will change nextState - return nextState == 1 - } - } -} - -/** - * A sequence that skips the specified number of values from the underlying [sequence] and returns - * all values after that. - */ -internal class DropSequence ( - private val sequence: Sequence, - private val count: Int -) : Sequence, DropTakeSequence { - init { - require (count >= 0) { "count must be non-negative, but was $count." } - } - - override fun drop(n: Int): Sequence = DropSequence(sequence, count + n) - override fun take(n: Int): Sequence = SubSequence(sequence, count, count + n) - - override fun iterator(): Iterator = object : Iterator { - val iterator = sequence.iterator() - var left = count - - // Shouldn't be called from constructor to avoid premature iteration - private fun drop() { - while (left > 0 && iterator.hasNext()) { - iterator.next() - left-- - } - } - - override fun next(): T { - drop() - return iterator.next() - } - - override fun hasNext(): Boolean { - drop() - return iterator.hasNext() - } - } -} - -/** - * A sequence that skips the values from the underlying [sequence] while the given [predicate] returns `true` and returns - * all values after that. - */ -internal class DropWhileSequence -constructor(private val sequence: Sequence, - private val predicate: (T) -> Boolean -) : Sequence { - - override fun iterator(): Iterator = object : Iterator { - val iterator = sequence.iterator() - var dropState: Int = -1 // -1 for not dropping, 1 for nextItem, 0 for normal iteration - var nextItem: T? = null - - private fun drop() { - while (iterator.hasNext()) { - val item = iterator.next() - if (!predicate(item)) { - nextItem = item - dropState = 1 - return - } - } - dropState = 0 - } - - override fun next(): T { - if (dropState == -1) - drop() - - if (dropState == 1) { - @Suppress("UNCHECKED_CAST") - val result = nextItem as T - nextItem = null - dropState = 0 - return result - } - return iterator.next() - } - - override fun hasNext(): Boolean { - if (dropState == -1) - drop() - return dropState == 1 || iterator.hasNext() - } - } -} - - -internal class DistinctSequence(private val source : Sequence, private val keySelector : (T) -> K) : Sequence { - override fun iterator(): Iterator = DistinctIterator(source.iterator(), keySelector) -} - -private class DistinctIterator(private val source : Iterator, private val keySelector : (T) -> K) : AbstractIterator() { - private val observed = HashSet() - - override fun computeNext() { - while (source.hasNext()) { - val next = source.next() - val key = keySelector(next) - - if (observed.add(key)) { - setNext(next) - return - } - } - - done() - } -} - -private class GeneratorSequence(private val getInitialValue: () -> T?, private val getNextValue: (T) -> T?): Sequence { - override fun iterator(): Iterator = object : Iterator { - var nextItem: T? = null - var nextState: Int = -2 // -2 for initial unknown, -1 for next unknown, 0 for done, 1 for continue - - private fun calcNext() { - nextItem = if (nextState == -2) getInitialValue() else getNextValue(nextItem!!) - nextState = if (nextItem == null) 0 else 1 - } - - override fun next(): T { - if (nextState < 0) - calcNext() - - if (nextState == 0) - throw NoSuchElementException() - val result = nextItem as T - // Do not clean nextItem (to avoid keeping reference on yielded instance) -- need to keep state for getNextValue - nextState = -1 - return result - } - - override fun hasNext(): Boolean { - if (nextState < 0) - calcNext() - return nextState == 1 - } - } -} - -/** - * Returns a wrapper sequence that provides values of this sequence, but ensures it can be iterated only one time. - * - * [IllegalStateException] is thrown on iterating the returned sequence from the second time. - */ -public fun Sequence.constrainOnce(): Sequence { - // as? does not work in js - //return this as? ConstrainedOnceSequence ?: ConstrainedOnceSequence(this) - return if (this is ConstrainedOnceSequence) this else ConstrainedOnceSequence(this) -} - @FixmeConcurrency -private class ConstrainedOnceSequence(sequence: Sequence) : Sequence { +internal actual class ConstrainedOnceSequence actual constructor(sequence: Sequence) : Sequence { // TODO: not MT friendly. private var sequenceRef : Sequence? = sequence - override fun iterator(): Iterator { + override actual fun iterator(): Iterator { val sequence = sequenceRef if (sequence == null) throw IllegalStateException("This sequence can be consumed only once.") sequenceRef = null return sequence.iterator() } } - -/** - * Returns a sequence which invokes the function to calculate the next value on each iteration until the function returns `null`. - * - * The returned sequence is constrained to be iterated only once. - * - * @see constrainOnce - * @see kotlin.coroutines.experimental.buildSequence - * - * @sample samples.collections.Sequences.Building.generateSequence - */ -public fun generateSequence(nextFunction: () -> T?): Sequence { - return GeneratorSequence(nextFunction, { nextFunction() }).constrainOnce() -} - -/** - * Returns a sequence defined by the starting value [seed] and the function [nextFunction], - * which is invoked to calculate the next value based on the previous one on each iteration. - * - * The sequence produces values until it encounters first `null` value. - * If [seed] is `null`, an empty sequence is produced. - * - * The sequence can be iterated multiple times, each time starting with [seed]. - * - * @see kotlin.coroutines.experimental.buildSequence - * - * @sample samples.collections.Sequences.Building.generateSequenceWithSeed - */ -@kotlin.internal.LowPriorityInOverloadResolution -public fun generateSequence(seed: T?, nextFunction: (T) -> T?): Sequence = - if (seed == null) - EmptySequence - else - GeneratorSequence({ seed }, nextFunction) - -/** - * Returns a sequence defined by the function [seedFunction], which is invoked to produce the starting value, - * and the [nextFunction], which is invoked to calculate the next value based on the previous one on each iteration. - * - * The sequence produces values until it encounters first `null` value. - * If [seedFunction] returns `null`, an empty sequence is produced. - * - * The sequence can be iterated multiple times. - * - * @see kotlin.coroutines.experimental.buildSequence - * - * @sample samples.collections.Sequences.Building.generateSequenceWithLazySeed - */ -public fun generateSequence(seedFunction: () -> T?, nextFunction: (T) -> T?): Sequence = - GeneratorSequence(seedFunction, nextFunction) - - - -/** - * Returns `true` if [element] is found in the sequence. - */ -public operator fun <@kotlin.internal.OnlyInputTypes T> Sequence.contains(element: T): Boolean { - return indexOf(element) >= 0 -} - -/** - * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this sequence. - */ -public fun Sequence.elementAt(index: Int): T { - return elementAtOrElse(index) { throw IndexOutOfBoundsException("Sequence doesn't contain element at index $index.") } -} - -/** - * Returns an element at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this sequence. - */ -public fun Sequence.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T { - if (index < 0) - return defaultValue(index) - val iterator = iterator() - var count = 0 - while (iterator.hasNext()) { - val element = iterator.next() - if (index == count++) - return element - } - return defaultValue(index) -} - -/** - * Returns an element at the given [index] or `null` if the [index] is out of bounds of this sequence. - */ -public fun Sequence.elementAtOrNull(index: Int): T? { - if (index < 0) - return null - val iterator = iterator() - var count = 0 - while (iterator.hasNext()) { - val element = iterator.next() - if (index == count++) - return element - } - return null -} - -/** - * Returns the first element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun Sequence.find(predicate: (T) -> Boolean): T? { - return firstOrNull(predicate) -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -@kotlin.internal.InlineOnly -public inline fun Sequence.findLast(predicate: (T) -> Boolean): T? { - return lastOrNull(predicate) -} - -/** - * Returns first element. - * @throws [NoSuchElementException] if the sequence is empty. - */ -public fun Sequence.first(): T { - val iterator = iterator() - if (!iterator.hasNext()) - throw NoSuchElementException("Sequence is empty.") - return iterator.next() -} - -/** - * Returns the first element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun Sequence.first(predicate: (T) -> Boolean): T { - for (element in this) if (predicate(element)) return element - throw NoSuchElementException("Sequence contains no element matching the predicate.") -} - -/** - * Returns the first element, or `null` if the sequence is empty. - */ -public fun Sequence.firstOrNull(): T? { - val iterator = iterator() - if (!iterator.hasNext()) - return null - return iterator.next() -} - -/** - * Returns the first element matching the given [predicate], or `null` if element was not found. - */ -public inline fun Sequence.firstOrNull(predicate: (T) -> Boolean): T? { - for (element in this) if (predicate(element)) return element - return null -} - -/** - * Returns first index of [element], or -1 if the sequence does not contain element. - */ -public fun <@kotlin.internal.OnlyInputTypes T> Sequence.indexOf(element: T): Int { - var index = 0 - for (item in this) { - if (element == item) - return index - index++ - } - return -1 -} - -/** - * Returns index of the first element matching the given [predicate], or -1 if the sequence does not contain such element. - */ -public inline fun Sequence.indexOfFirst(predicate: (T) -> Boolean): Int { - var index = 0 - for (item in this) { - if (predicate(item)) - return index - index++ - } - return -1 -} - -/** - * Returns index of the last element matching the given [predicate], or -1 if the sequence does not contain such element. - */ -public inline fun Sequence.indexOfLast(predicate: (T) -> Boolean): Int { - var lastIndex = -1 - var index = 0 - for (item in this) { - if (predicate(item)) - lastIndex = index - index++ - } - return lastIndex -} - -/** - * Returns the last element. - * @throws [NoSuchElementException] if the sequence is empty. - */ -public fun Sequence.last(): T { - val iterator = iterator() - if (!iterator.hasNext()) - throw NoSuchElementException("Sequence is empty.") - var last = iterator.next() - while (iterator.hasNext()) - last = iterator.next() - return last -} - -/** - * Returns the last element matching the given [predicate]. - * @throws [NoSuchElementException] if no such element is found. - */ -public inline fun Sequence.last(predicate: (T) -> Boolean): T { - var last: T? = null - var found = false - for (element in this) { - if (predicate(element)) { - last = element - found = true - } - } - if (!found) throw NoSuchElementException("Sequence contains no element matching the predicate.") - @Suppress("UNCHECKED_CAST") - return last as T -} - -/** - * Returns last index of [element], or -1 if the sequence does not contain element. - */ -public fun <@kotlin.internal.OnlyInputTypes T> Sequence.lastIndexOf(element: T): Int { - var lastIndex = -1 - var index = 0 - for (item in this) { - if (element == item) - lastIndex = index - index++ - } - return lastIndex -} - -/** - * Returns the last element, or `null` if the sequence is empty. - */ -public fun Sequence.lastOrNull(): T? { - val iterator = iterator() - if (!iterator.hasNext()) - return null - var last = iterator.next() - while (iterator.hasNext()) - last = iterator.next() - return last -} - -/** - * Returns the last element matching the given [predicate], or `null` if no such element was found. - */ -public inline fun Sequence.lastOrNull(predicate: (T) -> Boolean): T? { - var last: T? = null - for (element in this) { - if (predicate(element)) { - last = element - } - } - return last -} - -/** - * Returns the single element, or throws an exception if the sequence is empty or has more than one element. - */ -public fun Sequence.single(): T { - val iterator = iterator() - if (!iterator.hasNext()) - throw NoSuchElementException("Sequence is empty.") - val single = iterator.next() - if (iterator.hasNext()) - throw IllegalArgumentException("Sequence has more than one element.") - return single -} - -/** - * Returns the single element matching the given [predicate], or throws exception if there is no or more than one matching element. - */ -public inline fun Sequence.single(predicate: (T) -> Boolean): T { - var single: T? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) throw IllegalArgumentException("Sequence contains more than one matching element.") - single = element - found = true - } - } - if (!found) throw NoSuchElementException("Sequence contains no element matching the predicate.") - @Suppress("UNCHECKED_CAST") - return single as T -} - -/** - * Returns single element, or `null` if the sequence is empty or has more than one element. - */ -public fun Sequence.singleOrNull(): T? { - val iterator = iterator() - if (!iterator.hasNext()) - return null - val single = iterator.next() - if (iterator.hasNext()) - return null - return single -} - -/** - * Returns the single element matching the given [predicate], or `null` if element was not found or more than one element was found. - */ -public inline fun Sequence.singleOrNull(predicate: (T) -> Boolean): T? { - var single: T? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) return null - single = element - found = true - } - } - if (!found) return null - return single -} - -/** - * Returns a sequence containing all elements except first [n] elements. - */ -public fun Sequence.drop(n: Int): Sequence { - require(n >= 0) { "Requested element count $n is less than zero." } - return when { - n == 0 -> this - this is DropTakeSequence -> this.drop(n) - else -> DropSequence(this, n) - } -} - -/** - * Returns a sequence containing all elements except first elements that satisfy the given [predicate]. - */ -public fun Sequence.dropWhile(predicate: (T) -> Boolean): Sequence { - return DropWhileSequence(this, predicate) -} - -/** - * Returns a sequence containing only elements matching the given [predicate]. - */ -public fun Sequence.filter(predicate: (T) -> Boolean): Sequence { - return FilteringSequence(this, true, predicate) -} - -/** - * Returns a sequence containing only elements matching the given [predicate]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public fun Sequence.filterIndexed(predicate: (Int, T) -> Boolean): Sequence { - // TODO: Rewrite with generalized MapFilterIndexingSequence - return TransformingSequence(FilteringSequence(IndexingSequence(this), true, { predicate(it.index, it.value) }), { it.value }) -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - * @param [predicate] function that takes the index of an element and the element itself - * and returns the result of predicate evaluation on the element. - */ -public inline fun > Sequence.filterIndexedTo(destination: C, predicate: (Int, T) -> Boolean): C { - forEachIndexed { index, element -> - if (predicate(index, element)) destination.add(element) - } - return destination -} - -/** - * Returns a sequence containing all elements that are instances of specified type parameter R. - */ -public inline fun Sequence<*>.filterIsInstance(): Sequence<@kotlin.internal.NoInfer R> { - @Suppress("UNCHECKED_CAST") - return filter { it is R } as Sequence -} - -/** - * Appends all elements that are instances of specified type parameter R to the given [destination]. - */ -@Suppress("UNUSED_PARAMETER") -public inline fun > Sequence<*>.filterIsInstanceTo(destination: C): C { - for (element in this) if (element is R) destination.add(element) - return destination -} - -/** - * Returns a sequence containing all elements not matching the given [predicate]. - */ -public fun Sequence.filterNot(predicate: (T) -> Boolean): Sequence { - return FilteringSequence(this, false, predicate) -} - -/** - * Returns a sequence containing all elements that are not `null`. - */ -public fun Sequence.filterNotNull(): Sequence { - @Suppress("UNCHECKED_CAST") - return filterNot { it == null } as Sequence -} - -/** - * Appends all elements that are not `null` to the given [destination]. - */ -public fun , T : Any> Sequence.filterNotNullTo(destination: C): C { - for (element in this) if (element != null) destination.add(element) - return destination -} - -/** - * Appends all elements not matching the given [predicate] to the given [destination]. - */ -public inline fun > Sequence.filterNotTo(destination: C, predicate: (T) -> Boolean): C { - for (element in this) if (!predicate(element)) destination.add(element) - return destination -} - -/** - * Appends all elements matching the given [predicate] to the given [destination]. - */ -public inline fun > Sequence.filterTo(destination: C, predicate: (T) -> Boolean): C { - for (element in this) if (predicate(element)) destination.add(element) - return destination -} - -/** - * Returns a sequence containing first [n] elements. - */ -public fun Sequence.take(n: Int): Sequence { - require(n >= 0) { "Requested element count $n is less than zero." } - return when { - n == 0 -> emptySequence() - this is DropTakeSequence -> this.take(n) - else -> TakeSequence(this, n) - } -} - -/** - * Returns a sequence containing first elements satisfying the given [predicate]. - */ -public fun Sequence.takeWhile(predicate: (T) -> Boolean): Sequence { - return TakeWhileSequence(this, predicate) -} - -/** - * Returns a sequence that yields elements of this sequence sorted according to their natural sort order. - */ -public fun > Sequence.sorted(): Sequence { - return object : Sequence { - override fun iterator(): Iterator { - val sortedList = this@sorted.toMutableList() - sortedList.sort() - return sortedList.iterator() - } - } -} - -/** - * Returns a sequence that yields elements of this sequence sorted according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > Sequence.sortedBy(crossinline selector: (T) -> R?): Sequence { - return sortedWith(compareBy(selector)) -} - -/** - * Returns a sequence that yields elements of this sequence sorted descending according to natural sort order of the value returned by specified [selector] function. - */ -public inline fun > Sequence.sortedByDescending(crossinline selector: (T) -> R?): Sequence { - return sortedWith(compareByDescending(selector)) -} - -/** - * Returns a sequence that yields elements of this sequence sorted descending according to their natural sort order. - */ -public fun > Sequence.sortedDescending(): Sequence { - return sortedWith(reverseOrder()) -} - -/** - * Returns a sequence that yields elements of this sequence sorted according to the specified [comparator]. - */ -public fun Sequence.sortedWith(comparator: Comparator): Sequence { - return object : Sequence { - override fun iterator(): Iterator { - val sortedList = this@sortedWith.toMutableList() - sortedList.sortWith(comparator) - return sortedList.iterator() - } - } -} - -/** - * Returns a [Map] containing key-value pairs provided by [transform] function - * applied to elements of the given sequence. - * - * If any of two pairs would have the same key the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original sequence. - */ -public inline fun Sequence.associate(transform: (T) -> Pair): Map { - return associateTo(LinkedHashMap(), transform) -} - -/** - * Returns a [Map] containing the elements from the given sequence indexed by the key - * returned from [keySelector] function applied to each element. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original sequence. - */ -public inline fun Sequence.associateBy(keySelector: (T) -> K): Map { - return associateByTo(LinkedHashMap(), keySelector) -} - -/** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to elements of the given sequence. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original sequence. - */ -public inline fun Sequence.associateBy(keySelector: (T) -> K, valueTransform: (T) -> V): Map { - return associateByTo(LinkedHashMap(), keySelector, valueTransform) -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function applied to each element of the given sequence - * and value is the element itself. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > Sequence.associateByTo(destination: M, keySelector: (T) -> K): M { - for (element in this) { - destination.put(keySelector(element), element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and - * and value is provided by the [valueTransform] function applied to elements of the given sequence. - * - * If any two elements would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > Sequence.associateByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V): M { - for (element in this) { - destination.put(keySelector(element), valueTransform(element)) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs - * provided by [transform] function applied to each element of the given sequence. - * - * If any of two pairs would have the same key the last one gets added to the map. - */ -public inline fun > Sequence.associateTo(destination: M, transform: (T) -> Pair): M { - for (element in this) { - destination += transform(element) - } - return destination -} - -/** - * Appends all elements to the given [destination] collection. - */ -public fun > Sequence.toCollection(destination: C): C { - for (item in this) { - destination.add(item) - } - return destination -} - -/** - * Returns a [HashSet] of all elements. - */ -public fun Sequence.toHashSet(): HashSet { - return toCollection(HashSet()) -} - -/** - * Returns a [List] containing all elements. - */ -public fun Sequence.toList(): List { - return this.toMutableList().optimizeReadOnlyList() -} - -/** - * Returns a [MutableList] filled with all elements of this sequence. - */ -public fun Sequence.toMutableList(): MutableList { - return toCollection(ArrayList()) -} - -/** - * Returns a [Set] of all elements. - * - * The returned set preserves the element iteration order of the original sequence. - */ -public fun Sequence.toSet(): Set { - return toCollection(LinkedHashSet()).optimizeReadOnlySet() -} - -/** - * Returns a single sequence of all elements from results of [transform] function being invoked on each element of original sequence. - */ -public fun Sequence.flatMap(transform: (T) -> Sequence): Sequence { - return FlatteningSequence(this, transform, { it.iterator() }) -} - -/** - * Appends all elements yielded from results of [transform] function being invoked on each element of original sequence, to the given [destination]. - */ -public inline fun > Sequence.flatMapTo(destination: C, transform: (T) -> Sequence): C { - for (element in this) { - val list = transform(element) - destination.addAll(list) - } - return destination -} - -/** - * Groups elements of the original sequence by the key returned by the given [keySelector] function - * applied to each element and returns a map where each group key is associated with a list of corresponding elements. - * - * The returned map preserves the entry iteration order of the keys produced from the original sequence. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun Sequence.groupBy(keySelector: (T) -> K): Map> { - return groupByTo(LinkedHashMap>(), keySelector) -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original sequence - * by the key returned by the given [keySelector] function applied to the element - * and returns a map where each group key is associated with a list of corresponding values. - * - * The returned map preserves the entry iteration order of the keys produced from the original sequence. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun Sequence.groupBy(keySelector: (T) -> K, valueTransform: (T) -> V): Map> { - return groupByTo(LinkedHashMap>(), keySelector, valueTransform) -} - -/** - * Groups elements of the original sequence by the key returned by the given [keySelector] function - * applied to each element and puts to the [destination] map each group key associated with a list of corresponding elements. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun >> Sequence.groupByTo(destination: M, keySelector: (T) -> K): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(element) - } - return destination -} - -/** - * Groups values returned by the [valueTransform] function applied to each element of the original sequence - * by the key returned by the given [keySelector] function applied to the element - * and puts to the [destination] map each group key associated with a list of corresponding values. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun >> Sequence.groupByTo(destination: M, keySelector: (T) -> K, valueTransform: (T) -> V): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(valueTransform(element)) - } - return destination -} - -/** - * Creates a [Grouping] source from a sequence to be used later with one of group-and-fold operations - * using the specified [keySelector] function to extract a key from each element. - */ -public inline fun Sequence.groupingBy(crossinline keySelector: (T) -> K): Grouping { - return object : Grouping { - override fun sourceIterator(): Iterator = this@groupingBy.iterator() - override fun keyOf(element: T): K = keySelector(element) - } -} - -/** - * Returns a sequence containing the results of applying the given [transform] function - * to each element in the original sequence. - */ -public fun Sequence.map(transform: (T) -> R): Sequence { - return TransformingSequence(this, transform) -} - -/** - * Returns a sequence containing the results of applying the given [transform] function - * to each element and its index in the original sequence. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public fun Sequence.mapIndexed(transform: (Int, T) -> R): Sequence { - return TransformingIndexedSequence(this, transform) -} - -/** - * Returns a sequence containing only the non-null results of applying the given [transform] function - * to each element and its index in the original sequence. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public fun Sequence.mapIndexedNotNull(transform: (Int, T) -> R?): Sequence { - return TransformingIndexedSequence(this, transform).filterNotNull() -} - -/** - * Applies the given [transform] function to each element and its index in the original sequence - * and appends only the non-null results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > Sequence.mapIndexedNotNullTo(destination: C, transform: (Int, T) -> R?): C { - forEachIndexed { index, element -> transform(index, element)?.let { destination.add(it) } } - return destination -} - -/** - * Applies the given [transform] function to each element and its index in the original sequence - * and appends the results to the given [destination]. - * @param [transform] function that takes the index of an element and the element itself - * and returns the result of the transform applied to the element. - */ -public inline fun > Sequence.mapIndexedTo(destination: C, transform: (Int, T) -> R): C { - var index = 0 - for (item in this) - destination.add(transform(index++, item)) - return destination -} - -/** - * Returns a sequence containing only the non-null results of applying the given [transform] function - * to each element in the original sequence. - */ -public fun Sequence.mapNotNull(transform: (T) -> R?): Sequence { - return TransformingSequence(this, transform).filterNotNull() -} - -/** - * Applies the given [transform] function to each element in the original sequence - * and appends only the non-null results to the given [destination]. - */ -public inline fun > Sequence.mapNotNullTo(destination: C, transform: (T) -> R?): C { - forEach { element -> transform(element)?.let { destination.add(it) } } - return destination -} - -/** - * Applies the given [transform] function to each element of the original sequence - * and appends the results to the given [destination]. - */ -public inline fun > Sequence.mapTo(destination: C, transform: (T) -> R): C { - for (item in this) - destination.add(transform(item)) - return destination -} - -/** - * Returns a sequence of [IndexedValue] for each element of the original sequence. - */ -public fun Sequence.withIndex(): Sequence> { - return IndexingSequence(this) -} - -/** - * Returns a sequence containing only distinct elements from the given sequence. - * - * The elements in the resulting sequence are in the same order as they were in the source sequence. - */ -public fun Sequence.distinct(): Sequence { - return this.distinctBy { it } -} - -/** - * Returns a sequence containing only elements from the given sequence - * having distinct keys returned by the given [selector] function. - * - * The elements in the resulting sequence are in the same order as they were in the source sequence. - */ -public fun Sequence.distinctBy(selector: (T) -> K): Sequence { - return DistinctSequence(this, selector) -} - -/** - * Returns a mutable set containing all distinct elements from the given sequence. - * - * The returned set preserves the element iteration order of the original sequence. - */ -public fun Sequence.toMutableSet(): MutableSet { - val set = LinkedHashSet() - for (item in this) set.add(item) - return set -} - -/** - * Returns `true` if all elements match the given [predicate]. - */ -public inline fun Sequence.all(predicate: (T) -> Boolean): Boolean { - for (element in this) if (!predicate(element)) return false - return true -} - -/** - * Returns `true` if sequence has at least one element. - */ -public fun Sequence.any(): Boolean { - for (element in this) return true - return false -} - -/** - * Returns `true` if at least one element matches the given [predicate]. - */ -public inline fun Sequence.any(predicate: (T) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return true - return false -} - -/** - * Returns the number of elements in this sequence. - */ -public fun Sequence.count(): Int { - var count = 0 - for (element in this) count++ - return count -} - -/** - * Returns the number of elements matching the given [predicate]. - */ -public inline fun Sequence.count(predicate: (T) -> Boolean): Int { - var count = 0 - for (element in this) if (predicate(element)) count++ - return count -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun Sequence.fold(initial: R, operation: (R, T) -> R): R { - var accumulator = initial - for (element in this) accumulator = operation(accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right - * to current accumulator value and each element with its index in the original sequence. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself, and calculates the next accumulator value. - */ -public inline fun Sequence.foldIndexed(initial: R, operation: (Int, R, T) -> R): R { - var index = 0 - var accumulator = initial - for (element in this) accumulator = operation(index++, accumulator, element) - return accumulator -} - -/** - * Performs the given [action] on each element. - */ -public inline fun Sequence.forEach(action: (T) -> Unit): Unit { - for (element in this) action(element) -} - -/** - * Performs the given [action] on each element, providing sequential index with the element. - * @param [action] function that takes the index of an element and the element itself - * and performs the desired action on the element. - */ -public inline fun Sequence.forEachIndexed(action: (Int, T) -> Unit): Unit { - var index = 0 - for (item in this) action(index++, item) -} - -/** - * Returns the largest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -public fun Sequence.max(): Double? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var max = iterator.next() - if (max.isNaN()) return max - while (iterator.hasNext()) { - val e = iterator.next() - if (e.isNaN()) return e - if (max < e) max = e - } - return max -} - -/** - * Returns the largest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -public fun Sequence.max(): Float? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var max = iterator.next() - if (max.isNaN()) return max - while (iterator.hasNext()) { - val e = iterator.next() - if (e.isNaN()) return e - if (max < e) max = e - } - return max -} - -/** - * Returns the largest element or `null` if there are no elements. - */ -public fun > Sequence.max(): T? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var max = iterator.next() - while (iterator.hasNext()) { - val e = iterator.next() - if (max < e) max = e - } - return max -} - -/** - * Returns the first element yielding the largest value of the given function or `null` if there are no elements. - */ -public inline fun > Sequence.maxBy(selector: (T) -> R): T? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var maxElem = iterator.next() - var maxValue = selector(maxElem) - while (iterator.hasNext()) { - val e = iterator.next() - val v = selector(e) - if (maxValue < v) { - maxElem = e - maxValue = v - } - } - return maxElem -} - -/** - * Returns the first element having the largest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun Sequence.maxWith(comparator: Comparator): T? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var max = iterator.next() - while (iterator.hasNext()) { - val e = iterator.next() - if (comparator.compare(max, e) < 0) max = e - } - return max -} - -/** - * Returns the smallest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -public fun Sequence.min(): Double? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var min = iterator.next() - if (min.isNaN()) return min - while (iterator.hasNext()) { - val e = iterator.next() - if (e.isNaN()) return e - if (min > e) min = e - } - return min -} - -/** - * Returns the smallest element or `null` if there are no elements. - * - * If any of elements is `NaN` returns `NaN`. - */ -public fun Sequence.min(): Float? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var min = iterator.next() - if (min.isNaN()) return min - while (iterator.hasNext()) { - val e = iterator.next() - if (e.isNaN()) return e - if (min > e) min = e - } - return min -} - -/** - * Returns the smallest element or `null` if there are no elements. - */ -public fun > Sequence.min(): T? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var min = iterator.next() - while (iterator.hasNext()) { - val e = iterator.next() - if (min > e) min = e - } - return min -} - -/** - * Returns the first element yielding the smallest value of the given function or `null` if there are no elements. - */ -public inline fun > Sequence.minBy(selector: (T) -> R): T? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var minElem = iterator.next() - var minValue = selector(minElem) - while (iterator.hasNext()) { - val e = iterator.next() - val v = selector(e) - if (minValue > v) { - minElem = e - minValue = v - } - } - return minElem -} - -/** - * Returns the first element having the smallest value according to the provided [comparator] or `null` if there are no elements. - */ -public fun Sequence.minWith(comparator: Comparator): T? { - val iterator = iterator() - if (!iterator.hasNext()) return null - var min = iterator.next() - while (iterator.hasNext()) { - val e = iterator.next() - if (comparator.compare(min, e) > 0) min = e - } - return min -} - -/** - * Returns `true` if the sequence has no elements. - */ -public fun Sequence.none(): Boolean { - for (element in this) return false - return true -} - -/** - * Returns `true` if no elements match the given [predicate]. - */ -public inline fun Sequence.none(predicate: (T) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return false - return true -} - -/** - * Returns a sequence which performs the given [action] on each element of the original sequence as they pass though it. - */ -public fun Sequence.onEach(action: (T) -> Unit): Sequence { - return map { - action(it) - it - } -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right to current accumulator value and each element. - */ -public inline fun Sequence.reduce(operation: (S, T) -> S): S { - val iterator = this.iterator() - if (!iterator.hasNext()) throw UnsupportedOperationException("Empty sequence can't be reduced.") - var accumulator: S = iterator.next() - while (iterator.hasNext()) { - accumulator = operation(accumulator, iterator.next()) - } - return accumulator -} - -/** - * Accumulates value starting with the first element and applying [operation] from left to right - * to current accumulator value and each element with its index in the original sequence. - * @param [operation] function that takes the index of an element, current accumulator value - * and the element itself and calculates the next accumulator value. - */ -public inline fun Sequence.reduceIndexed(operation: (Int, S, T) -> S): S { - val iterator = this.iterator() - if (!iterator.hasNext()) throw UnsupportedOperationException("Empty sequence can't be reduced.") - var index = 1 - var accumulator: S = iterator.next() - while (iterator.hasNext()) { - accumulator = operation(index++, accumulator, iterator.next()) - } - return accumulator -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the sequence. - */ -public inline fun Sequence.sumBy(selector: (T) -> Int): Int { - var sum: Int = 0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each element in the sequence. - */ -public inline fun Sequence.sumByDouble(selector: (T) -> Double): Double { - var sum: Double = 0.0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns an original collection containing all the non-`null` elements, throwing an [IllegalArgumentException] if there are any `null` elements. - */ -public fun Sequence.requireNoNulls(): Sequence { - return map { it ?: throw IllegalArgumentException("null element found in $this.") } -} - -/** - * Splits this sequence into a sequence of lists each not exceeding the given [size]. - * - * The last list in the resulting sequence may have less elements than the given [size]. - * - * @param size the number of elements to take in each list, must be positive and can be greater than the number of elements in this sequence. - * - * @sample samples.collections.Collections.Transformations.chunked - * - * The operation is _intermediate_ and _stateful_. - */ -@SinceKotlin("1.2") -public fun Sequence.chunked(size: Int): Sequence> { - return windowed(size, size, partialWindows = true) -} - -/** - * Splits this sequence into several lists each not exceeding the given [size] - * and applies the given [transform] function to an each. - * - * @return sequence of results of the [transform] applied to an each list. - * - * Note that the list passed to the [transform] function is ephemeral and is valid only inside that function. - * You should not store it or allow it to escape in some way, unless you made a snapshot of it. - * The last list may have less elements than the given [size]. - * - * @param size the number of elements to take in each list, must be positive and can be greater than the number of elements in this sequence. - * - * @sample samples.text.Strings.chunkedTransform - * - * The operation is _intermediate_ and _stateful_. - */ -@SinceKotlin("1.2") -public fun Sequence.chunked(size: Int, transform: (List) -> R): Sequence { - return windowed(size, size, partialWindows = true, transform = transform) -} - -/** - * Returns a sequence containing all elements of the original sequence without the first occurrence of the given [element]. - */ -public operator fun Sequence.minus(element: T): Sequence { - return object: Sequence { - override fun iterator(): Iterator { - var removed = false - return this@minus.filter { if (!removed && it == element) { removed = true; false } else true }.iterator() - } - } -} - -/** - * Returns a sequence containing all elements of original sequence except the elements contained in the given [elements] array. - * - * Note that the source sequence and the array being subtracted are iterated only when an `iterator` is requested from - * the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result. - */ -public operator fun Sequence.minus(elements: Array): Sequence { - if (elements.isEmpty()) return this - return object: Sequence { - override fun iterator(): Iterator { - val other = elements.toHashSet() - return this@minus.filterNot { it in other }.iterator() - } - } -} - -/** - * Returns a sequence containing all elements of original sequence except the elements contained in the given [elements] collection. - * - * Note that the source sequence and the collection being subtracted are iterated only when an `iterator` is requested from - * the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result. - */ -public operator fun Sequence.minus(elements: Iterable): Sequence { - return object: Sequence { - override fun iterator(): Iterator { - val other = elements.convertToSetForSetOperation() - if (other.isEmpty()) - return this@minus.iterator() - else - return this@minus.filterNot { it in other }.iterator() - } - } -} - -/** - * Returns a sequence containing all elements of original sequence except the elements contained in the given [elements] sequence. - * - * Note that the source sequence and the sequence being subtracted are iterated only when an `iterator` is requested from - * the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result. - */ -public operator fun Sequence.minus(elements: Sequence): Sequence { - return object: Sequence { - override fun iterator(): Iterator { - val other = elements.toHashSet() - if (other.isEmpty()) - return this@minus.iterator() - else - return this@minus.filterNot { it in other }.iterator() - } - } -} - -/** - * Returns a sequence containing all elements of the original sequence without the first occurrence of the given [element]. - */ -@kotlin.internal.InlineOnly -public inline fun Sequence.minusElement(element: T): Sequence { - return minus(element) -} - -/** - * Splits the original sequence into pair of lists, - * where *first* list contains elements for which [predicate] yielded `true`, - * while *second* list contains elements for which [predicate] yielded `false`. - */ -public inline fun Sequence.partition(predicate: (T) -> Boolean): Pair, List> { - val first = ArrayList() - val second = ArrayList() - for (element in this) { - if (predicate(element)) { - first.add(element) - } else { - second.add(element) - } - } - return Pair(first, second) -} - -/** - * Returns a sequence containing all elements of the original sequence and then the given [element]. - */ -public operator fun Sequence.plus(element: T): Sequence { - return sequenceOf(this, sequenceOf(element)).flatten() -} - -/** - * Returns a sequence containing all elements of original sequence and then all elements of the given [elements] array. - * - * Note that the source sequence and the array being added are iterated only when an `iterator` is requested from - * the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result. - */ -public operator fun Sequence.plus(elements: Array): Sequence { - return this.plus(elements.asList()) -} - -/** - * Returns a sequence containing all elements of original sequence and then all elements of the given [elements] collection. - * - * Note that the source sequence and the collection being added are iterated only when an `iterator` is requested from - * the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result. - */ -public operator fun Sequence.plus(elements: Iterable): Sequence { - return sequenceOf(this, elements.asSequence()).flatten() -} - -/** - * Returns a sequence containing all elements of original sequence and then all elements of the given [elements] sequence. - * - * Note that the source sequence and the sequence being added are iterated only when an `iterator` is requested from - * the resulting sequence. Changing any of them between successive calls to `iterator` may affect the result. - */ -public operator fun Sequence.plus(elements: Sequence): Sequence { - return sequenceOf(this, elements).flatten() -} - -/** - * Returns a sequence containing all elements of the original sequence and then the given [element]. - */ -@kotlin.internal.InlineOnly -public inline fun Sequence.plusElement(element: T): Sequence { - return plus(element) -} - -/** - * Returns a sequence of snapshots of the window of the given [size] - * sliding along this sequence with the given [step], where each - * snapshot is a list. - * - * Several last lists may have less elements than the given [size]. - * - * Both [size] and [step] must be positive and can be greater than the number of elements in this sequence. - * @param size the number of elements to take in each window - * @param step the number of elements to move the window forward by on an each step, by default 1 - * @param partialWindows controls whether or not to keep partial windows in the end if any, - * by default `false` which means partial windows won't be preserved - * - * @sample samples.collections.Sequences.Transformations.takeWindows - */ -@SinceKotlin("1.2") -public fun Sequence.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false): Sequence> { - return windowedSequence(size, step, partialWindows, reuseBuffer = false) -} - -/** - * Returns a sequence of results of applying the given [transform] function to - * an each list representing a view over the window of the given [size] - * sliding along this sequence with the given [step]. - * - * Note that the list passed to the [transform] function is ephemeral and is valid only inside that function. - * You should not store it or allow it to escape in some way, unless you made a snapshot of it. - * Several last lists may have less elements than the given [size]. - * - * Both [size] and [step] must be positive and can be greater than the number of elements in this sequence. - * @param size the number of elements to take in each window - * @param step the number of elements to move the window forward by on an each step, by default 1 - * @param partialWindows controls whether or not to keep partial windows in the end if any, - * by default `false` which means partial windows won't be preserved - * - * @sample samples.collections.Sequences.Transformations.averageWindows - */ -@SinceKotlin("1.2") -public fun Sequence.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false, transform: (List) -> R): Sequence { - return windowedSequence(size, step, partialWindows, reuseBuffer = true).map(transform) -} - -/** - * Returns a sequence of pairs built from elements of both sequences with same indexes. - * Resulting sequence has length of shortest input sequence. - */ -public infix fun Sequence.zip(other: Sequence): Sequence> { - return MergingSequence(this, other) { t1, t2 -> t1 to t2 } -} - -/** - * Returns a sequence of values built from elements of both collections with same indexes using provided [transform]. Resulting sequence has length of shortest input sequences. - */ -public fun Sequence.zip(other: Sequence, transform: (T, R) -> V): Sequence { - return MergingSequence(this, other, transform) -} - -/** - * Returns a sequence of pairs of each two adjacent elements in this sequence. - * - * The returned sequence is empty if this sequence contains less than two elements. - * - * @sample samples.collections.Collections.Transformations.zipWithNext - * - * The operation is _intermediate_ and _stateless_. - */ -@SinceKotlin("1.2") -public fun Sequence.zipWithNext(): Sequence> { - return zipWithNext { a, b -> a to b } -} - -/** - * Returns a sequence containing the results of applying the given [transform] function - * to an each pair of two adjacent elements in this sequence. - * - * The returned sequence is empty if this sequence contains less than two elements. - * - * @sample samples.collections.Collections.Transformations.zipWithNextToFindDeltas - * - * The operation is _intermediate_ and _stateless_. - */ -@SinceKotlin("1.2") -public fun Sequence.zipWithNext(transform: (a: T, b: T) -> R): Sequence { - return buildSequence result@ { - val iterator = iterator() - if (!iterator.hasNext()) return@result - var current = iterator.next() - while (iterator.hasNext()) { - val next = iterator.next() - yield(transform(current, next)) - current = next - } - } -} - -/** - * Appends the string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun Sequence.joinTo(buffer: A, separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): A { - buffer.append(prefix) - var count = 0 - for (element in this) { - if (++count > 1) buffer.append(separator) - if (limit < 0 || count <= limit) { - buffer.appendElement(element, transform) - } else break - } - if (limit >= 0 && count > limit) buffer.append(truncated) - buffer.append(postfix) - return buffer -} - -/** - * Creates a string from all the elements separated using [separator] and using the given [prefix] and [postfix] if supplied. - * - * If the collection could be huge, you can specify a non-negative value of [limit], in which case only the first [limit] - * elements will be appended, followed by the [truncated] string (which defaults to "..."). - */ -public fun Sequence.joinToString(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "", limit: Int = -1, truncated: CharSequence = "...", transform: ((T) -> CharSequence)? = null): String { - return joinTo(StringBuilder(), separator, prefix, postfix, limit, truncated, transform).toString() -} - -/** - * Creates an [Iterable] instance that wraps the original sequence returning its elements when being iterated. - */ -public fun Sequence.asIterable(): Iterable { - return Iterable { this.iterator() } -} - -/** - * Returns this sequence as a [Sequence]. - */ -@kotlin.internal.InlineOnly -public inline fun Sequence.asSequence(): Sequence { - return this -} - -/** - * Returns an average value of elements in the sequence. - */ -public fun Sequence.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) 0.0 else sum / count -} - -/** - * Returns an average value of elements in the sequence. - */ -public fun Sequence.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) 0.0 else sum / count -} - -/** - * Returns an average value of elements in the sequence. - */ -public fun Sequence.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) 0.0 else sum / count -} - -/** - * Returns an average value of elements in the sequence. - */ -public fun Sequence.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) 0.0 else sum / count -} - -/** - * Returns an average value of elements in the sequence. - */ -public fun Sequence.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) 0.0 else sum / count -} - -/** - * Returns an average value of elements in the sequence. - */ -public fun Sequence.average(): Double { - var sum: Double = 0.0 - var count: Int = 0 - for (element in this) { - sum += element - count += 1 - } - return if (count == 0) 0.0 else sum / count -} - -/** - * Returns the sum of all elements in the sequence. - */ -public fun Sequence.sum(): Int { - var sum: Int = 0 - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the sequence. - */ -public fun Sequence.sum(): Int { - var sum: Int = 0 - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the sequence. - */ -public fun Sequence.sum(): Int { - var sum: Int = 0 - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the sequence. - */ -public fun Sequence.sum(): Long { - var sum: Long = 0L - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the sequence. - */ -public fun Sequence.sum(): Float { - var sum: Float = 0.0f - for (element in this) { - sum += element - } - return sum -} - -/** - * Returns the sum of all elements in the sequence. - */ -public fun Sequence.sum(): Double { - var sum: Double = 0.0 - for (element in this) { - sum += element - } - return sum -} - diff --git a/runtime/src/main/kotlin/kotlin/text/Appendable.kt b/runtime/src/main/kotlin/kotlin/text/Appendable.kt index f273243eb1e..a3085f808a1 100644 --- a/runtime/src/main/kotlin/kotlin/text/Appendable.kt +++ b/runtime/src/main/kotlin/kotlin/text/Appendable.kt @@ -16,44 +16,8 @@ package kotlin.text -interface Appendable { - fun append(c: Char): Appendable - fun append(csq: CharSequence?): Appendable - fun append(csq: CharSequence?, start: Int, end: Int): Appendable -} - -/** - * Appends all arguments to the given [Appendable]. - */ -public fun T.append(vararg value: CharSequence?): T { - for (item in value) - append(item) - return this -} - -/** - * Appends all arguments to the given StringBuilder. - */ -public fun StringBuilder.append(vararg value: String?): StringBuilder { - for (item in value) - append(item) - return this -} - -/** - * Appends all arguments to the given StringBuilder. - */ -public fun StringBuilder.append(vararg value: Any?): StringBuilder { - for (item in value) - append(item) - return this -} - -internal fun Appendable.appendElement(element: T, transform: ((T) -> CharSequence)?) { - when { - transform != null -> append(transform(element)) - element is CharSequence -> append(element) - element is Char -> append(element) - else -> append(element.toString()) - } +actual interface Appendable { + actual fun append(c: Char): Appendable + actual fun append(csq: CharSequence?): Appendable + actual fun append(csq: CharSequence?, start: Int, end: Int): Appendable } diff --git a/runtime/src/main/kotlin/kotlin/text/Char.kt b/runtime/src/main/kotlin/kotlin/text/Char.kt index daa8618cf48..0da3b4516ac 100644 --- a/runtime/src/main/kotlin/kotlin/text/Char.kt +++ b/runtime/src/main/kotlin/kotlin/text/Char.kt @@ -60,7 +60,7 @@ external public fun Char.isISOControl(): Boolean * Returns `true` if the character is whitespace. */ @SymbolName("Kotlin_Char_isWhitespace") -external public fun Char.isWhitespace(): Boolean +external public actual fun Char.isWhitespace(): Boolean /** * Returns `true` if this character is upper case. @@ -78,28 +78,28 @@ external public fun Char.isLowerCase(): Boolean * Converts this character to uppercase. */ @SymbolName("Kotlin_Char_toUpperCase") -external public fun Char.toUpperCase(): Char +external public actual fun Char.toUpperCase(): Char /** * Converts this character to lowercase. */ @SymbolName("Kotlin_Char_toLowerCase") -external public fun Char.toLowerCase(): Char +external public actual fun Char.toLowerCase(): Char /** * Returns `true` if this character is a Unicode high-surrogate code unit (also known as leading-surrogate code unit). */ @SymbolName("Kotlin_Char_isHighSurrogate") -external public fun Char.isHighSurrogate(): Boolean +external public actual fun Char.isHighSurrogate(): Boolean /** * Returns `true` if this character is a Unicode low-surrogate code unit (also known as trailing-surrogate code unit). */ @SymbolName("Kotlin_Char_isLowSurrogate") -external public fun Char.isLowSurrogate(): Boolean +external public actual fun Char.isLowSurrogate(): Boolean -internal fun digitOf(char: Char, radix: Int): Int = digitOfChecked(char, checkRadix(radix)) +internal actual fun digitOf(char: Char, radix: Int): Int = digitOfChecked(char, checkRadix(radix)) @SymbolName("Kotlin_Char_digitOfChecked") external internal fun digitOfChecked(char: Char, radix: Int): Int @@ -117,7 +117,7 @@ external internal fun Char.getType(): Int * Checks whether the given [radix] is valid radix for string to number and number to string conversion. */ @PublishedApi -internal fun checkRadix(radix: Int): Int { +internal actual fun checkRadix(radix: Int): Int { if(radix !in Char.MIN_RADIX..Char.MAX_RADIX) { throw IllegalArgumentException("radix $radix was not in valid range ${Char.MIN_RADIX..Char.MAX_RADIX}") } diff --git a/runtime/src/main/kotlin/kotlin/text/Indent.kt b/runtime/src/main/kotlin/kotlin/text/Indent.kt deleted file mode 100644 index aad2cb875ba..00000000000 --- a/runtime/src/main/kotlin/kotlin/text/Indent.kt +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.text - -/** - * Trims leading whitespace characters followed by [marginPrefix] from every line of a source string and removes - * the first and the last lines if they are blank (notice difference blank vs empty). - * - * Doesn't affect a line if it doesn't contain [marginPrefix] except the first and the last blank lines. - * - * Doesn't preserve the original line endings. - * - * @param marginPrefix non-blank string, which is used as a margin delimiter. Default is `|` (pipe character). - * - * @sample samples.text.Strings.trimMargin - * @see trimIndent - * @see kotlin.text.isWhitespace - */ -public fun String.trimMargin(marginPrefix: String = "|"): String = - replaceIndentByMargin("", marginPrefix) - -/** - * Detects indent by [marginPrefix] as it does [trimMargin] and replace it with [newIndent]. - * - * @param marginPrefix non-blank string, which is used as a margin delimiter. Default is `|` (pipe character). - */ -public fun String.replaceIndentByMargin(newIndent: String = "", marginPrefix: String = "|"): String { - require(marginPrefix.isNotBlank()) { "marginPrefix must be non-blank string." } - val lines = lines() - - return lines.reindent(length + newIndent.length * lines.size, getIndentFunction(newIndent), { line -> - val firstNonWhitespaceIndex = line.indexOfFirst { !it.isWhitespace() } - - when { - firstNonWhitespaceIndex == -1 -> null - line.startsWith(marginPrefix, firstNonWhitespaceIndex) -> line.substring(firstNonWhitespaceIndex + marginPrefix.length) - else -> null - } - }) -} - -/** - * Detects a common minimal indent of all the input lines, removes it from every line and also removes the first and the last - * lines if they are blank (notice difference blank vs empty). - * - * Note that blank lines do not affect the detected indent level. - * - * In case if there are non-blank lines with no leading whitespace characters (no indent at all) then the - * common indent is 0, and therefore this function doesn't change the indentation. - * - * Doesn't preserve the original line endings. - * - * @sample samples.text.Strings.trimIndent - * @see trimMargin - * @see kotlin.text.isBlank - */ -public fun String.trimIndent(): String = replaceIndent("") - -/** - * Detects a common minimal indent like it does [trimIndent] and replaces it with the specified [newIndent]. - */ -public fun String.replaceIndent(newIndent: String = ""): String { - val lines = lines() - - val minCommonIndent = lines - .filter(String::isNotBlank) - .map(String::indentWidth) - .min() ?: 0 - - return lines.reindent(length + newIndent.length * lines.size, getIndentFunction(newIndent), { line -> line.drop(minCommonIndent) }) -} - -/** - * Prepends [indent] to every line of the original string. - * - * Doesn't preserve the original line endings. - */ -public fun String.prependIndent(indent: String = " "): String = - lineSequence() - .map { - when { - it.isBlank() -> { - when { - it.length < indent.length -> indent - else -> it - } - } - else -> indent + it - } - } - .joinToString("\n") - -private fun String.indentWidth(): Int = indexOfFirst { !it.isWhitespace() }.let { if (it == -1) length else it } - -private fun getIndentFunction(indent: String) = when { - indent.isEmpty() -> { line: String -> line } - else -> { line: String -> indent + line } -} - -private inline fun List.reindent(resultSizeEstimate: Int, indentAddFunction: (String) -> String, indentCutFunction: (String) -> String?): String { - val lastIndex = lastIndex - return mapIndexedNotNull { index, value -> - if ((index == 0 || index == lastIndex) && value.isBlank()) - null - else - indentCutFunction(value)?.let(indentAddFunction) ?: value - } - .joinTo(StringBuilder(resultSizeEstimate), "\n") - .toString() -} diff --git a/runtime/src/main/kotlin/kotlin/text/MatchResult.kt b/runtime/src/main/kotlin/kotlin/text/MatchResult.kt deleted file mode 100644 index b43f4bb36ec..00000000000 --- a/runtime/src/main/kotlin/kotlin/text/MatchResult.kt +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin.text - -import kotlin.text.regex.* - -/** - * Represents a collection of captured groups in a single match of a regular expression. - * - * This collection has size of `groupCount + 1` where `groupCount` is the count of groups in the regular expression. - * Groups are indexed from 1 to `groupCount` and group with the index 0 corresponds to the entire match. - * - * An element of the collection at the particular index can be `null`, - * if the corresponding group in the regular expression is optional and - * there was no match captured by that group. - */ -// TODO: Add MatchGroup -interface MatchGroupCollection : Collection { - - /** Returns a group with the specified [index]. - * - * @return An instance of [MatchGroup] if the group with the specified [index] was matched or `null` otherwise. - * - * Groups are indexed from 1 to the count of groups in the regular expression. A group with the index 0 - * corresponds to the entire match. - */ - operator fun get(index: Int): MatchGroup? -} - -/** - * Extends [MatchGroupCollection] by introducing a way to get matched groups by name, when regex supports it. - */ -@SinceKotlin("1.1") interface MatchNamedGroupCollection : MatchGroupCollection { - /** - * Returns a named group with the specified [name]. - * @return An instance of [MatchGroup] if the group with the specified [name] was matched or `null` otherwise. - */ - operator fun get(name: String): MatchGroup? -} - -/** - * Represents the results from a single regular expression match. - */ -interface MatchResult { - /** The range of indices in the original string where match was captured. */ - val range: IntRange - /** The substring from the input string captured by this match. */ - val value: String - /** - * A collection of groups matched by the regular expression. - * - * This collection has size of `groupCount + 1` where `groupCount` is the count of groups in the regular expression. - * Groups are indexed from 1 to `groupCount` and group with the index 0 corresponds to the entire match. - */ - val groups: MatchGroupCollection - /** - * A list of matched indexed group values. - * - * This list has size of `groupCount + 1` where `groupCount` is the count of groups in the regular expression. - * Groups are indexed from 1 to `groupCount` and group with the index 0 corresponds to the entire match. - * - * If the group in the regular expression is optional and there were no match captured by that group, - * corresponding item in [groupValues] is an empty string. - * - * @sample: samples.text.Regexps.matchDestructuringToGroupValues - */ - val groupValues: List - - /** - * An instance of [MatchResult.Destructured] wrapper providing components for destructuring assignment of group values. - * - * component1 corresponds to the value of the first group, component2 — of the second, and so on. - * - * @sample: samples.text.Regexps.matchDestructuring - */ - val destructured: Destructured get() = Destructured(this) - - /** Returns a new [MatchResult] with the results for the next match, starting at the position - * at which the last match ended (at the character after the last matched character). - */ - fun next(): MatchResult? - - /** - * Provides components for destructuring assignment of group values. - * - * [component1] corresponds to the value of the first group, [component2] — of the second, and so on. - * - * If the group in the regular expression is optional and there were no match captured by that group, - * corresponding component value is an empty string. - * - * @sample: samples.text.Regexps.matchDestructuringToGroupValues - */ - class Destructured internal constructor(val match: MatchResult) { - - @kotlin.internal.InlineOnly operator inline fun component1(): String = match.groupValues[1] - @kotlin.internal.InlineOnly operator inline fun component2(): String = match.groupValues[2] - @kotlin.internal.InlineOnly operator inline fun component3(): String = match.groupValues[3] - @kotlin.internal.InlineOnly operator inline fun component4(): String = match.groupValues[4] - @kotlin.internal.InlineOnly operator inline fun component5(): String = match.groupValues[5] - @kotlin.internal.InlineOnly operator inline fun component6(): String = match.groupValues[6] - @kotlin.internal.InlineOnly operator inline fun component7(): String = match.groupValues[7] - @kotlin.internal.InlineOnly operator inline fun component8(): String = match.groupValues[8] - @kotlin.internal.InlineOnly operator inline fun component9(): String = match.groupValues[9] - @kotlin.internal.InlineOnly operator inline fun component10(): String = match.groupValues[10] - /** - * Returns destructured group values as a list of strings. - * First value in the returned list corresponds to the value of the first group, and so on. - * - * @sample: samples.text.Regexps.matchDestructuringToGroupValues - */ - fun toList(): List = match.groupValues.subList(1, match.groupValues.size) - } -} diff --git a/runtime/src/main/kotlin/kotlin/text/Regex.kt b/runtime/src/main/kotlin/kotlin/text/Regex.kt index dfc3ad61647..d617cb9fa36 100644 --- a/runtime/src/main/kotlin/kotlin/text/Regex.kt +++ b/runtime/src/main/kotlin/kotlin/text/Regex.kt @@ -31,7 +31,7 @@ private fun fromInt(value: Int): Set = /** * Provides enumeration values to use to set regular expression options. */ -enum class RegexOption(override val value: Int, override val mask: Int = value) : FlagEnum { +actual enum class RegexOption(override val value: Int, override val mask: Int = value) : FlagEnum { // common /** Enables case-insensitive matching. Case comparison is Unicode-aware. */ @@ -72,50 +72,50 @@ enum class RegexOption(override val value: Int, override val mask: Int = value) * * The [range] property is available on JVM only. */ -data class MatchGroup(val value: String, val range: IntRange) +actual data class MatchGroup(actual val value: String, val range: IntRange) /** * Represents an immutable regular expression. * * For pattern syntax reference see [Pattern] */ -class Regex internal constructor(internal val nativePattern: Pattern) { +actual class Regex internal constructor(internal val nativePattern: Pattern) { enum class Mode { FIND, MATCH } /** Creates a regular expression from the specified [pattern] string and the default options. */ - constructor(pattern: String): this(Pattern(pattern)) + actual constructor(pattern: String): this(Pattern(pattern)) /** Creates a regular expression from the specified [pattern] string and the specified single [option]. */ - constructor(pattern: String, option: RegexOption): this(Pattern(pattern, ensureUnicodeCase(option.value))) + actual constructor(pattern: String, option: RegexOption): this(Pattern(pattern, ensureUnicodeCase(option.value))) /** Creates a regular expression from the specified [pattern] string and the specified set of [options]. */ - constructor(pattern: String, options: Set): this(Pattern(pattern, ensureUnicodeCase(options.toInt()))) + actual constructor(pattern: String, options: Set): this(Pattern(pattern, ensureUnicodeCase(options.toInt()))) /** The pattern string of this regular expression. */ - val pattern: String + actual val pattern: String get() = nativePattern.pattern private val startNode = nativePattern.startNode /** The set of options that were used to create this regular expression. */ - val options: Set = fromInt(nativePattern.flags) + actual val options: Set = fromInt(nativePattern.flags) - companion object { + actual companion object { /** Returns a literal regex for the specified [literal] string. */ - fun fromLiteral(literal: String): Regex = Regex(literal, RegexOption.LITERAL) + actual fun fromLiteral(literal: String): Regex = Regex(literal, RegexOption.LITERAL) /** Returns a literal pattern for the specified [literal] string. */ - fun escape(literal: String): String = Pattern.quote(literal) + actual fun escape(literal: String): String = Pattern.quote(literal) /** * Returns a replacement string for the given one that has all backslashes * and dollar signs escaped. */ - fun escapeReplacement(literal: String): String { + actual fun escapeReplacement(literal: String): String { if (!literal.contains('\\') && !literal.contains('$')) return literal @@ -148,10 +148,10 @@ class Regex internal constructor(internal val nativePattern: Pattern) { } /** Indicates whether the regular expression matches the entire [input]. */ - infix fun matches(input: CharSequence): Boolean = doMatch(input, Mode.MATCH) != null + actual infix fun matches(input: CharSequence): Boolean = doMatch(input, Mode.MATCH) != null /** Indicates whether the regular expression can find at least one match in the specified [input]. */ - fun containsMatchIn(input: CharSequence): Boolean = find(input) != null + actual fun containsMatchIn(input: CharSequence): Boolean = find(input) != null /** * Returns the first match of a regular expression in the [input], beginning at the specified [startIndex]. @@ -159,7 +159,7 @@ class Regex internal constructor(internal val nativePattern: Pattern) { * @param startIndex An index to start search with, by default 0. Must be not less than zero and not greater than `input.length()` * @return An instance of [MatchResult] if match was found or `null` otherwise. */ - fun find(input: CharSequence, startIndex: Int = 0): MatchResult? { + actual fun find(input: CharSequence, startIndex: Int): MatchResult? { if (startIndex < 0 || startIndex > input.length) { throw IndexOutOfBoundsException() // TODO: Add a message. } @@ -179,7 +179,7 @@ class Regex internal constructor(internal val nativePattern: Pattern) { * Returns a sequence of all occurrences of a regular expression within the [input] string, * beginning at the specified [startIndex]. */ - fun findAll(input: CharSequence, startIndex: Int = 0): Sequence + actual fun findAll(input: CharSequence, startIndex: Int): Sequence = generateSequence({ find(input, startIndex) }, MatchResult::next) /** @@ -187,7 +187,7 @@ class Regex internal constructor(internal val nativePattern: Pattern) { * * @return An instance of [MatchResult] if the entire input matches or `null` otherwise. */ - fun matchEntire(input: CharSequence): MatchResult?= doMatch(input, Mode.MATCH) + actual fun matchEntire(input: CharSequence): MatchResult?= doMatch(input, Mode.MATCH) private fun processReplacement(match: MatchResult, replacement: String): String { val result = StringBuilder(replacement.length) @@ -227,7 +227,7 @@ class Regex internal constructor(internal val nativePattern: Pattern) { * * @param replacement A replacement expression that can include substitutions. */ - fun replace(input: CharSequence, replacement: String): String + actual fun replace(input: CharSequence, replacement: String): String = replace(input) { match -> processReplacement(match, replacement) } /** @@ -235,7 +235,7 @@ class Regex internal constructor(internal val nativePattern: Pattern) { * the given function [transform] that takes [MatchResult] and returns a string to be used as a * replacement for that match. */ - fun replace(input: CharSequence, transform: (MatchResult) -> CharSequence): String { + actual fun replace(input: CharSequence, transform: (MatchResult) -> CharSequence): String { var match: MatchResult? = find(input) ?: return input.toString() var lastStart = 0 @@ -261,7 +261,7 @@ class Regex internal constructor(internal val nativePattern: Pattern) { * * @param replacement A replacement expression that can include substitutions. See [Matcher.appendReplacement] for details. */ - fun replaceFirst(input: CharSequence, replacement: String): String + actual fun replaceFirst(input: CharSequence, replacement: String): String = replaceFirst(input) { match -> processReplacement(match, replacement) } /** @@ -270,7 +270,7 @@ class Regex internal constructor(internal val nativePattern: Pattern) { * @param limit Non-negative value specifying the maximum number of substrings the string can be split to. * Zero by default means no limit is set. */ - fun split(input: CharSequence, limit: Int = 0): List { + actual fun split(input: CharSequence, limit: Int): List { require(limit >= 0, { "Limit must be non-negative, but was $limit." } ) if (input.isEmpty()) { return listOf("") diff --git a/runtime/src/main/kotlin/kotlin/text/StringBuilder.kt b/runtime/src/main/kotlin/kotlin/text/StringBuilder.kt index ccb1d623fbe..89d3a62d7a2 100644 --- a/runtime/src/main/kotlin/kotlin/text/StringBuilder.kt +++ b/runtime/src/main/kotlin/kotlin/text/StringBuilder.kt @@ -71,58 +71,47 @@ private external fun insertString(array: CharArray, start: Int, value: String): @SymbolName("Kotlin_StringBuilder_insertInt") private external fun insertInt(array: CharArray, start: Int, value: Int): Int -/** - * Builds new string by populating newly created [StringBuilder] using provided [builderAction] - * and then converting it to [String]. - */ -@kotlin.internal.InlineOnly -public inline fun buildString(builderAction: StringBuilder.() -> Unit): String = - StringBuilder().apply(builderAction).toString() - -/** - * Builds new string by populating newly created [StringBuilder] initialized with the given [capacity] - * using provided [builderAction] and then converting it to [String]. - */ -@SinceKotlin("1.1") -@kotlin.internal.InlineOnly -public inline fun buildString(capacity: Int, builderAction: StringBuilder.() -> Unit): String = - StringBuilder(capacity).apply(builderAction).toString() - /** * Sets the character at the specified [index] to the specified [value]. */ @kotlin.internal.InlineOnly public inline operator fun StringBuilder.set(index: Int, value: Char): Unit = this.setCharAt(index, value) -class StringBuilder private constructor ( +actual class StringBuilder private constructor ( private var array: CharArray ) : CharSequence, Appendable { - constructor() : this(10) + actual constructor() : this(10) - constructor(capacity: Int) : this(CharArray(capacity)) + actual constructor(capacity: Int) : this(CharArray(capacity)) constructor(string: String) : this(string.toCharArray()) { - length = array.size + _length = array.size } - constructor(sequence: CharSequence): this(sequence.length) { - append(sequence) + actual constructor(content: CharSequence): this(content.length) { + append(content) } - override var length: Int = 0 + private var _length: Int = 0 set(capacity) { ensureCapacity(capacity) field = capacity } + actual override val length: Int + get() = _length - override fun get(index: Int): Char { + actual override fun get(index: Int): Char { checkIndex(index) return array[index] } - override fun subSequence(startIndex: Int, endIndex: Int): CharSequence = substring(startIndex, endIndex) + fun setLength(l: Int) { + _length = l + } - override fun toString(): String = fromCharArray(array, 0, length) + actual override fun subSequence(startIndex: Int, endIndex: Int): CharSequence = substring(startIndex, endIndex) + + override fun toString(): String = fromCharArray(array, 0, _length) fun substring(startIndex: Int, endIndex: Int): String { checkInsertIndex(startIndex) @@ -131,8 +120,8 @@ class StringBuilder private constructor ( } fun trimToSize() { - if (length < array.size) - array = array.copyOf(length) + if (_length < array.size) + array = array.copyOf(_length) } fun ensureCapacity(capacity: Int) { @@ -145,22 +134,22 @@ class StringBuilder private constructor ( } // Based on Apache Harmony implementation. - fun reverse(): StringBuilder { + actual fun reverse(): StringBuilder { if (this.length < 2) { return this } - var end = length - 1 + var end = _length - 1 var front = 0 var frontLeadingChar = array[0] var endTrailingChar = array[end] var allowFrontSurrogate = true var allowEndSurrogate = true - while (front < length / 2) { + while (front < _length / 2) { var frontTrailingChar = array[front + 1] var endLeadingChar = array[end - 1] var surrogateAtFront = allowFrontSurrogate && frontTrailingChar.isLowSurrogate() && frontLeadingChar.isHighSurrogate() - if (surrogateAtFront && length < 3) { + if (surrogateAtFront && _length < 3) { return this } var surrogateAtEnd = allowEndSurrogate && endTrailingChar.isLowSurrogate() && endLeadingChar.isHighSurrogate() @@ -205,7 +194,7 @@ class StringBuilder private constructor ( front++ end-- } - if (length % 2 == 1 && (!allowEndSurrogate || !allowFrontSurrogate)) { + if (_length % 2 == 1 && (!allowEndSurrogate || !allowFrontSurrogate)) { array[end] = if (allowFrontSurrogate) endTrailingChar else frontLeadingChar } return this @@ -219,7 +208,7 @@ class StringBuilder private constructor ( array[i] = array[i - 1] } array[index] = c - length++ + _length++ return this } @@ -237,14 +226,14 @@ class StringBuilder private constructor ( val extraLength = end - start ensureExtraCapacity(extraLength) - array.copyRangeTo(array, index, length, index + extraLength) + array.copyRangeTo(array, index, _length, index + extraLength) var from = start var to = index while (from < end) { array[to++] = toInsert[from++] } - length += extraLength + _length += extraLength return this } @@ -252,18 +241,18 @@ class StringBuilder private constructor ( checkInsertIndex(index) ensureExtraCapacity(chars.size) - array.copyRangeTo(array, index, length, index + chars.size) + array.copyRangeTo(array, index, _length, index + chars.size) chars.copyRangeTo(array, 0, chars.size, index) - length += chars.size + _length += chars.size return this } fun insert(index: Int, string: String): StringBuilder { checkInsertIndex(index) ensureExtraCapacity(string.length) - array.copyRangeTo(array, index, length, index + string.length) - length += insertString(array, index, string) + array.copyRangeTo(array, index, _length, index + string.length) + _length += insertString(array, index, string) return this } @@ -279,39 +268,39 @@ class StringBuilder private constructor ( // Of Appenable. - override fun append(c: Char) : StringBuilder { + actual override fun append(c: Char) : StringBuilder { ensureExtraCapacity(1) - array[length++] = c + array[_length++] = c return this } - override fun append(csq: CharSequence?): StringBuilder { + actual override fun append(csq: CharSequence?): StringBuilder { // Kotlin/JVM processes null as if the argument was "null" char sequence. val toAppend = csq ?: "null" return append(toAppend, 0, toAppend.length) } - override fun append(csq: CharSequence?, start: Int, end: Int): StringBuilder { + actual override fun append(csq: CharSequence?, start: Int, end: Int): StringBuilder { // Kotlin/JVM processes null as if the argument was "null" char sequence. val toAppend = csq ?: "null" if (start < 0 || end < start || start > toAppend.length) throw IndexOutOfBoundsException() ensureExtraCapacity(end - start) var index = start while (index < end) - array[length++] = toAppend[index++] + array[_length++] = toAppend[index++] return this } fun append(it: CharArray): StringBuilder { ensureExtraCapacity(it.size) - it.copyRangeTo(array, 0, it.size, length) - length += it.size + it.copyRangeTo(array, 0, it.size, _length) + _length += it.size return this } fun append(it: String): StringBuilder { ensureExtraCapacity(it.length) - length += insertString(array, length, it) + _length += insertString(array, _length, it) return this } @@ -321,18 +310,18 @@ class StringBuilder private constructor ( fun append(it: Short) = append(it.toString()) fun append(it: Int): StringBuilder { ensureExtraCapacity(11) - length += insertInt(array, length, it) + _length += insertInt(array, _length, it) return this } fun append(it: Long) = append(it.toString()) fun append(it: Float) = append(it.toString()) fun append(it: Double) = append(it.toString()) - fun append(it: Any?) = append(it.toString()) + actual fun append(obj: Any?): StringBuilder = append(obj.toString()) fun deleteCharAt(index: Int) { checkIndex(index) - array.copyRangeTo(array, index + 1, length, index) - --length + array.copyRangeTo(array, index + 1, _length, index) + --_length } fun setCharAt(index: Int, value: Char) { @@ -343,18 +332,18 @@ class StringBuilder private constructor ( // ---------------------------- private ---------------------------- private fun ensureExtraCapacity(n: Int) { - ensureCapacity(length + n) + ensureCapacity(_length + n) } private fun checkIndex(index: Int) { - if (index < 0 || index >= length) throw IndexOutOfBoundsException() + if (index < 0 || index >= _length) throw IndexOutOfBoundsException() } private fun checkInsertIndex(index: Int) { - if (index < 0 || index > length) throw IndexOutOfBoundsException() + if (index < 0 || index > _length) throw IndexOutOfBoundsException() } private fun checkInsertIndexFrom(index: Int, fromIndex: Int) { - if (index < fromIndex || index > length) throw IndexOutOfBoundsException() + if (index < fromIndex || index > _length) throw IndexOutOfBoundsException() } } diff --git a/runtime/src/main/kotlin/kotlin/text/StringNumberConversions.kt b/runtime/src/main/kotlin/kotlin/text/StringNumberConversions.kt index 551a6c58174..a30085f7a7a 100644 --- a/runtime/src/main/kotlin/kotlin/text/StringNumberConversions.kt +++ b/runtime/src/main/kotlin/kotlin/text/StringNumberConversions.kt @@ -23,14 +23,14 @@ import konan.internal.FloatingPointParser */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun Byte.toString(radix: Int): String = this.toInt().toString(checkRadix(radix)) +public actual inline fun Byte.toString(radix: Int): String = this.toInt().toString(checkRadix(radix)) /** * Returns a string representation of this [Short] value in the specified [radix]. */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun Short.toString(radix: Int): String = this.toInt().toString(checkRadix(radix)) +public actual inline fun Short.toString(radix: Int): String = this.toInt().toString(checkRadix(radix)) @SymbolName("Kotlin_Int_toStringRadix") external private fun intToString(value: Int, radix: Int): String @@ -41,7 +41,7 @@ external private fun intToString(value: Int, radix: Int): String @SinceKotlin("1.1") @kotlin.internal.InlineOnly @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") -public inline fun Int.toString(radix: Int): String = intToString(this, checkRadix(radix)) +public actual inline fun Int.toString(radix: Int): String = intToString(this, checkRadix(radix)) @SymbolName("Kotlin_Long_toStringRadix") external private fun longToString(value: Long, radix: Int): String @@ -52,20 +52,20 @@ external private fun longToString(value: Long, radix: Int): String @SinceKotlin("1.1") @kotlin.internal.InlineOnly @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") -public inline fun Long.toString(radix: Int): String = longToString(this, checkRadix(radix)) +public actual inline fun Long.toString(radix: Int): String = longToString(this, checkRadix(radix)) /** * Returns `true` if the contents of this string is equal to the word "true", ignoring case, and `false` otherwise. */ @kotlin.internal.InlineOnly -public inline fun String.toBoolean(): Boolean = this.equals("true", ignoreCase = true) +public actual inline fun String.toBoolean(): Boolean = this.equals("true", ignoreCase = true) /** * Parses the string as a signed [Byte] number and returns the result. * @throws NumberFormatException if the string is not a valid representation of a number. */ @kotlin.internal.InlineOnly -public inline fun String.toByte(): Byte = toByteOrNull() ?: throw NumberFormatException() +public actual inline fun String.toByte(): Byte = toByteOrNull() ?: throw NumberFormatException() /** * Parses the string as a signed [Byte] number and returns the result. @@ -73,14 +73,14 @@ public inline fun String.toByte(): Byte = toByteOrNull() ?: throw NumberFormatEx */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun String.toByte(radix: Int): Byte = toByteOrNull(radix) ?: throw NumberFormatException() +public actual inline fun String.toByte(radix: Int): Byte = toByteOrNull(radix) ?: throw NumberFormatException() /** * Parses the string as a [Short] number and returns the result. * @throws NumberFormatException if the string is not a valid representation of a number. */ @kotlin.internal.InlineOnly -public inline fun String.toShort(): Short = toShortOrNull() ?: throw NumberFormatException() +public actual inline fun String.toShort(): Short = toShortOrNull() ?: throw NumberFormatException() /** * Parses the string as a [Short] number and returns the result. @@ -88,14 +88,14 @@ public inline fun String.toShort(): Short = toShortOrNull() ?: throw NumberForma */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun String.toShort(radix: Int): Short = toShortOrNull(radix) ?: throw NumberFormatException() +public actual inline fun String.toShort(radix: Int): Short = toShortOrNull(radix) ?: throw NumberFormatException() /** * Parses the string as an [Int] number and returns the result. * @throws NumberFormatException if the string is not a valid representation of a number. */ @kotlin.internal.InlineOnly -public inline fun String.toInt(): Int = toIntOrNull() ?: throw NumberFormatException() +public actual inline fun String.toInt(): Int = toIntOrNull() ?: throw NumberFormatException() /** * Parses the string as an [Int] number and returns the result. @@ -103,14 +103,14 @@ public inline fun String.toInt(): Int = toIntOrNull() ?: throw NumberFormatExcep */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun String.toInt(radix: Int): Int = toIntOrNull(radix) ?: throw NumberFormatException() +public actual inline fun String.toInt(radix: Int): Int = toIntOrNull(radix) ?: throw NumberFormatException() /** * Parses the string as a [Long] number and returns the result. * @throws NumberFormatException if the string is not a valid representation of a number. */ @kotlin.internal.InlineOnly -public inline fun String.toLong(): Long = toLongOrNull() ?: throw NumberFormatException() +public actual inline fun String.toLong(): Long = toLongOrNull() ?: throw NumberFormatException() /** * Parses the string as a [Long] number and returns the result. @@ -118,7 +118,7 @@ public inline fun String.toLong(): Long = toLongOrNull() ?: throw NumberFormatEx */ @SinceKotlin("1.1") @kotlin.internal.InlineOnly -public inline fun String.toLong(radix: Int): Long = toLongOrNull(radix) ?: throw NumberFormatException() +public actual inline fun String.toLong(radix: Int): Long = toLongOrNull(radix) ?: throw NumberFormatException() /** * Parses the string as a [Float] number and returns the result. @@ -126,7 +126,7 @@ public inline fun String.toLong(radix: Int): Long = toLongOrNull(radix) ?: throw */ @kotlin.internal.InlineOnly @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") -public inline fun String.toFloat(): Float = FloatingPointParser.parseFloat(this) +public actual inline fun String.toFloat(): Float = FloatingPointParser.parseFloat(this) /** @@ -135,173 +135,14 @@ public inline fun String.toFloat(): Float = FloatingPointParser.parseFloat(this) */ @kotlin.internal.InlineOnly @Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE") -public inline fun String.toDouble(): Double = FloatingPointParser.parseDouble(this) - - -/** - * Parses the string as a signed [Byte] number and returns the result - * or `null` if the string is not a valid representation of a number. - */ -@SinceKotlin("1.1") -public fun String.toByteOrNull(): Byte? = toByteOrNull(radix = 10) - -/** - * Parses the string as a signed [Byte] number and returns the result - * or `null` if the string is not a valid representation of a number. - */ -@SinceKotlin("1.1") -public fun String.toByteOrNull(radix: Int): Byte? { - val int = this.toIntOrNull(radix) ?: return null - if (int < Byte.MIN_VALUE || int > Byte.MAX_VALUE) return null - return int.toByte() -} - -/** - * Parses the string as a [Short] number and returns the result - * or `null` if the string is not a valid representation of a number. - */ -@SinceKotlin("1.1") -public fun String.toShortOrNull(): Short? = toShortOrNull(radix = 10) - -/** - * Parses the string as a [Short] number and returns the result - * or `null` if the string is not a valid representation of a number. - */ -@SinceKotlin("1.1") -public fun String.toShortOrNull(radix: Int): Short? { - val int = this.toIntOrNull(radix) ?: return null - if (int < Short.MIN_VALUE || int > Short.MAX_VALUE) return null - return int.toShort() -} - -/** - * Parses the string as an [Int] number and returns the result - * or `null` if the string is not a valid representation of a number. - */ -@SinceKotlin("1.1") -public fun String.toIntOrNull(): Int? = toIntOrNull(radix = 10) - -/** - * Parses the string as an [Int] number and returns the result - * or `null` if the string is not a valid representation of a number. - */ -@SinceKotlin("1.1") -public fun String.toIntOrNull(radix: Int): Int? { - checkRadix(radix) - - val length = this.length - if (length == 0) return null - - val start: Int - val isNegative: Boolean - val limit: Int - - val firstChar = this[0] - if (firstChar < '0') { // Possible leading sign - if (length == 1) return null // non-digit (possible sign) only, no digits after - - start = 1 - - if (firstChar == '-') { - isNegative = true - limit = Int.MIN_VALUE - } else if (firstChar == '+') { - isNegative = false - limit = -Int.MAX_VALUE - } else - return null - } else { - start = 0 - isNegative = false - limit = -Int.MAX_VALUE - } - - - val limitBeforeMul = limit / radix - var result = 0 - for (i in start..(length - 1)) { - val digit = digitOf(this[i], radix) - - if (digit < 0) return null - if (result < limitBeforeMul) return null - - result *= radix - - if (result < limit + digit) return null - - result -= digit - } - - return if (isNegative) result else -result -} - -/** - * Parses the string as a [Long] number and returns the result - * or `null` if the string is not a valid representation of a number. - */ -@SinceKotlin("1.1") -public fun String.toLongOrNull(): Long? = toLongOrNull(radix = 10) - -/** - * Parses the string as a [Long] number and returns the result - * or `null` if the string is not a valid representation of a number. - */ -@SinceKotlin("1.1") -public fun String.toLongOrNull(radix: Int): Long? { - checkRadix(radix) - - val length = this.length - if (length == 0) return null - - val start: Int - val isNegative: Boolean - val limit: Long - - val firstChar = this[0] - if (firstChar < '0') { // Possible leading sign - if (length == 1) return null // non-digit (possible sign) only, no digits after - - start = 1 - - if (firstChar == '-') { - isNegative = true - limit = Long.MIN_VALUE - } else if (firstChar == '+') { - isNegative = false - limit = -Long.MAX_VALUE - } else - return null - } else { - start = 0 - isNegative = false - limit = -Long.MAX_VALUE - } - - - val limitBeforeMul = limit / radix - var result = 0L - for (i in start..(length - 1)) { - val digit = digitOf(this[i], radix) - - if (digit < 0) return null - if (result < limitBeforeMul) return null - - result *= radix - - if (result < limit + digit) return null - - result -= digit - } - - return if (isNegative) result else -result -} +public actual inline fun String.toDouble(): Double = FloatingPointParser.parseDouble(this) /** * Parses the string as a [Float] number and returns the result * or `null` if the string is not a valid representation of a number. */ @SinceKotlin("1.1") -public fun String.toFloatOrNull(): Float? { +public actual fun String.toFloatOrNull(): Float? { try { return toFloat() } catch (e: NumberFormatException) { @@ -314,7 +155,7 @@ public fun String.toFloatOrNull(): Float? { * or `null` if the string is not a valid representation of a number. */ @SinceKotlin("1.1") -public fun String.toDoubleOrNull(): Double? { +public actual fun String.toDoubleOrNull(): Double? { try { return toDouble() } catch (e: NumberFormatException) { diff --git a/runtime/src/main/kotlin/kotlin/text/Strings.kt b/runtime/src/main/kotlin/kotlin/text/Strings.kt index d2f5ce3b2ac..89987a79431 100644 --- a/runtime/src/main/kotlin/kotlin/text/Strings.kt +++ b/runtime/src/main/kotlin/kotlin/text/Strings.kt @@ -18,2546 +18,12 @@ package kotlin.text import kotlin.comparisons.* -/** - * Returns a sub sequence of this char sequence having leading and trailing characters matching the [predicate] trimmed. - */ -public inline fun CharSequence.trim(predicate: (Char) -> Boolean): CharSequence { - var startIndex = 0 - var endIndex = length - 1 - var startFound = false - - while (startIndex <= endIndex) { - val index = if (!startFound) startIndex else endIndex - val match = predicate(this[index]) - - if (!startFound) { - if (!match) - startFound = true - else - startIndex += 1 - } - else { - if (!match) - break - else - endIndex -= 1 - } - } - - return subSequence(startIndex, endIndex + 1) -} - -/** - * Returns a string with leading and trailing characters matching the [predicate] trimmed. - */ -public inline fun String.trim(predicate: (Char) -> Boolean): String - = (this as CharSequence).trim(predicate).toString() - -/** - * Returns a sub sequence of this char sequence having leading characters matching the [predicate] trimmed. - */ -public inline fun CharSequence.trimStart(predicate: (Char) -> Boolean): CharSequence { - for (index in this.indices) - if (!predicate(this[index])) - return subSequence(index, length) - - return "" -} - -/** - * Returns a string with leading characters matching the [predicate] trimmed. - */ -public inline fun String.trimStart(predicate: (Char) -> Boolean): String - = (this as CharSequence).trimStart(predicate).toString() - -/** - * Returns a sub sequence of this char sequence having trailing characters matching the [predicate] trimmed. - */ -public inline fun CharSequence.trimEnd(predicate: (Char) -> Boolean): CharSequence { - for (index in this.indices.reversed()) - if (!predicate(this[index])) - return substring(0, index + 1) - - return "" -} - -/** - * Returns a string with trailing characters matching the [predicate] trimmed. - */ -public inline fun String.trimEnd(predicate: (Char) -> Boolean): String - = (this as CharSequence).trimEnd(predicate).toString() - -/** - * Returns a sub sequence of this char sequence having leading and trailing characters from the [chars] array trimmed. - */ -public fun CharSequence.trim(vararg chars: Char): CharSequence = trim { it in chars } - -/** - * Returns a string with leading and trailing characters from the [chars] array trimmed. - */ -public fun String.trim(vararg chars: Char): String = trim { it in chars } - -/** - * Returns a sub sequence of this char sequence having leading and trailing characters from the [chars] array trimmed. - */ -public fun CharSequence.trimStart(vararg chars: Char): CharSequence = trimStart { it in chars } - -/** - * Returns a string with leading and trailing characters from the [chars] array trimmed. - */ -public fun String.trimStart(vararg chars: Char): String = trimStart { it in chars } - -/** - * Returns a sub sequence of this char sequence having trailing characters from the [chars] array trimmed. - */ -public fun CharSequence.trimEnd(vararg chars: Char): CharSequence = trimEnd { it in chars } - -/** - * Returns a string with trailing characters from the [chars] array trimmed. - */ -public fun String.trimEnd(vararg chars: Char): String = trimEnd { it in chars } - -/** - * Returns a sub sequence of this char sequence having leading and trailing whitespace trimmed. - */ -public fun CharSequence.trim(): CharSequence = trim { it.isWhitespace() } - -/** - * Returns a string with leading and trailing whitespace trimmed. - */ -@kotlin.internal.InlineOnly -public inline fun String.trim(): String = (this as CharSequence).trim().toString() - -/** - * Returns a sub sequence of this char sequence having leading whitespace removed. - */ -public fun CharSequence.trimStart(): CharSequence = trimStart { it.isWhitespace() } - -/** - * Returns a string with leading whitespace removed. - */ -@kotlin.internal.InlineOnly -public inline fun String.trimStart(): String = (this as CharSequence).trimStart().toString() - -/** - * Returns a sub sequence of this char sequence having trailing whitespace removed. - */ -public fun CharSequence.trimEnd(): CharSequence = trimEnd { it.isWhitespace() } - -/** - * Returns a string with trailing whitespace removed. - */ -@kotlin.internal.InlineOnly -public inline fun String.trimEnd(): String = (this as CharSequence).trimEnd().toString() - -/** - * Returns a char sequence with content of this char sequence padded at the beginning - * to the specified [length] with the specified character or space. - * - * @param length the desired string length. - * @param padChar the character to pad string with, if it has length less than the [length] specified. Space is used by default. - * @returns Returns a string, of length at least [length], consisting of string prepended with [padChar] as many times. - * as are necessary to reach that length. - */ -public fun CharSequence.padStart(length: Int, padChar: Char = ' '): CharSequence { - if (length < 0) - throw IllegalArgumentException("Desired length $length is less than zero.") - if (length <= this.length) - return this.subSequence(0, this.length) - - val sb = StringBuilder(length) - for (i in 1..(length - this.length)) - sb.append(padChar) - sb.append(this) - return sb -} - -/** - * Pads the string to the specified [length] at the beginning with the specified character or space. - * - * @param length the desired string length. - * @param padChar the character to pad string with, if it has length less than the [length] specified. Space is used by default. - * @returns Returns a string, of length at least [length], consisting of string prepended with [padChar] as many times. - * as are necessary to reach that length. - */ -public fun String.padStart(length: Int, padChar: Char = ' '): String - = (this as CharSequence).padStart(length, padChar).toString() - -/** - * Returns a char sequence with content of this char sequence padded at the end - * to the specified [length] with the specified character or space. - * - * @param length the desired string length. - * @param padChar the character to pad string with, if it has length less than the [length] specified. Space is used by default. - * @returns Returns a string, of length at least [length], consisting of string prepended with [padChar] as many times. - * as are necessary to reach that length. - */ -public fun CharSequence.padEnd(length: Int, padChar: Char = ' '): CharSequence { - if (length < 0) - throw IllegalArgumentException("Desired length $length is less than zero.") - if (length <= this.length) - return this.subSequence(0, this.length) - - val sb = StringBuilder(length) - sb.append(this) - for (i in 1..(length - this.length)) - sb.append(padChar) - return sb -} - -/** - * Pads the string to the specified [length] at the end with the specified character or space. - * - * @param length the desired string length. - * @param padChar the character to pad string with, if it has length less than the [length] specified. Space is used by default. - * @returns Returns a string, of length at least [length], consisting of string prepended with [padChar] as many times. - * as are necessary to reach that length. - */ -public fun String.padEnd(length: Int, padChar: Char = ' '): String - = (this as CharSequence).padEnd(length, padChar).toString() - -/** - * Returns `true` if this nullable char sequence is either `null` or empty. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence?.isNullOrEmpty(): Boolean = this == null || this.length == 0 - -/** - * Returns `true` if this char sequence is empty (contains no characters). - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.isEmpty(): Boolean = length == 0 - -/** - * Returns `true` if this char sequence is not empty. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.isNotEmpty(): Boolean = length > 0 - -// implemented differently in JVM and JS -//public fun String.isBlank(): Boolean = length() == 0 || all { it.isWhitespace() } - - -/** - * Returns `true` if this char sequence is not empty and contains some characters except of whitespace characters. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.isNotBlank(): Boolean = !isBlank() - -/** - * Returns `true` if this nullable char sequence is either `null` or empty or consists solely of whitespace characters. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence?.isNullOrBlank(): Boolean = this == null || this.isBlank() - -/** - * Iterator for characters of the given char sequence. - */ -public operator fun CharSequence.iterator(): CharIterator = object : CharIterator() { - private var index = 0 - - public override fun nextChar(): Char = get(index++) - - public override fun hasNext(): Boolean = index < length -} - -/** Returns the string if it is not `null`, or the empty string otherwise. */ -@kotlin.internal.InlineOnly -public inline fun String?.orEmpty(): String = this ?: "" - -/** - * Returns the range of valid character indices for this char sequence. - */ -public val CharSequence.indices: IntRange - get() = 0..length - 1 - -/** - * Returns the index of the last character in the char sequence or -1 if it is empty. - */ -public val CharSequence.lastIndex: Int - get() = this.length - 1 - -/** - * Returns `true` if this CharSequence has Unicode surrogate pair at the specified [index]. - */ -public fun CharSequence.hasSurrogatePairAt(index: Int): Boolean { - return index in 0..length - 2 - && this[index].isHighSurrogate() - && this[index + 1].isLowSurrogate() -} - -/** - * Returns a substring specified by the given [range] of indices. - */ -public fun String.substring(range: IntRange): String = substring(range.start, range.endInclusive + 1) - -/** - * Returns a subsequence of this char sequence specified by the given [range] of indices. - */ -public fun CharSequence.subSequence(range: IntRange): CharSequence = subSequence(range.start, range.endInclusive + 1) - -/** - * Returns a subsequence of this char sequence. - * - * This extension is chosen only for invocation with old-named parameters. - * Replace parameter names with the same as those of [CharSequence.subSequence]. - */ -@kotlin.internal.InlineOnly -@Deprecated("Use parameters named startIndex and endIndex.", ReplaceWith("subSequence(startIndex = start, endIndex = end)")) -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -public inline fun String.subSequence(start: Int, end: Int): CharSequence = subSequence(start, end) - -/** - * Returns a substring of chars from a range of this char sequence starting at the [startIndex] and ending right before the [endIndex]. - * - * @param startIndex the start index (inclusive). - * @param endIndex the end index (exclusive). If not specified, the length of the char sequence is used. - */ -// TODO: uncomment as soon as inlining works for stdlib. -@FixmeInline -@kotlin.internal.InlineOnly -public /*inline*/ fun CharSequence.substring(startIndex: Int, endIndex: Int = length): String = subSequence(startIndex, endIndex).toString() - -/** - * Returns a substring of chars at indices from the specified [range] of this char sequence. - */ -public fun CharSequence.substring(range: IntRange): String = subSequence(range.start, range.endInclusive + 1).toString() - -/** - * Returns a substring before the first occurrence of [delimiter]. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.substringBefore(delimiter: Char, missingDelimiterValue: String = this): String { - val index = indexOf(delimiter) - return if (index == -1) missingDelimiterValue else substring(0, index) -} - -/** - * Returns a substring before the first occurrence of [delimiter]. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.substringBefore(delimiter: String, missingDelimiterValue: String = this): String { - val index = indexOf(delimiter) - return if (index == -1) missingDelimiterValue else substring(0, index) -} - -/** - * Returns a substring after the first occurrence of [delimiter]. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.substringAfter(delimiter: Char, missingDelimiterValue: String = this): String { - val index = indexOf(delimiter) - return if (index == -1) missingDelimiterValue else substring(index + 1, length) -} - -/** - * Returns a substring after the first occurrence of [delimiter]. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.substringAfter(delimiter: String, missingDelimiterValue: String = this): String { - val index = indexOf(delimiter) - return if (index == -1) missingDelimiterValue else substring(index + delimiter.length, length) -} - -/** - * Returns a substring before the last occurrence of [delimiter]. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.substringBeforeLast(delimiter: Char, missingDelimiterValue: String = this): String { - val index = lastIndexOf(delimiter) - return if (index == -1) missingDelimiterValue else substring(0, index) -} - -/** - * Returns a substring before the last occurrence of [delimiter]. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.substringBeforeLast(delimiter: String, missingDelimiterValue: String = this): String { - val index = lastIndexOf(delimiter) - return if (index == -1) missingDelimiterValue else substring(0, index) -} - -/** - * Returns a substring after the last occurrence of [delimiter]. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.substringAfterLast(delimiter: Char, missingDelimiterValue: String = this): String { - val index = lastIndexOf(delimiter) - return if (index == -1) missingDelimiterValue else substring(index + 1, length) -} - -/** - * Returns a substring after the last occurrence of [delimiter]. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.substringAfterLast(delimiter: String, missingDelimiterValue: String = this): String { - val index = lastIndexOf(delimiter) - return if (index == -1) missingDelimiterValue else substring(index + delimiter.length, length) -} - -/** - * Returns a char sequence with content of this char sequence where its part at the given range - * is replaced with the [replacement] char sequence. - * @param startIndex the index of the first character to be replaced. - * @param endIndex the index of the first character after the replacement to keep in the string. - */ -public fun CharSequence.replaceRange(startIndex: Int, endIndex: Int, replacement: CharSequence): CharSequence { - if (endIndex < startIndex) - throw IndexOutOfBoundsException("End index ($endIndex) is less than start index ($startIndex).") - val sb = StringBuilder() - sb.append(this, 0, startIndex) - sb.append(replacement) - sb.append(this, endIndex, length) - return sb -} - -/** - * Replaces the part of the string at the given range with the [replacement] char sequence. - * @param startIndex the index of the first character to be replaced. - * @param endIndex the index of the first character after the replacement to keep in the string. - */ -@kotlin.internal.InlineOnly -public inline fun String.replaceRange(startIndex: Int, endIndex: Int, replacement: CharSequence): String - = (this as CharSequence).replaceRange(startIndex, endIndex, replacement).toString() - -/** - * Returns a char sequence with content of this char sequence where its part at the given [range] - * is replaced with the [replacement] char sequence. - * - * The end index of the [range] is included in the part to be replaced. - */ -public fun CharSequence.replaceRange(range: IntRange, replacement: CharSequence): CharSequence - = replaceRange(range.start, range.endInclusive + 1, replacement) - -/** - * Replace the part of string at the given [range] with the [replacement] string. - * - * The end index of the [range] is included in the part to be replaced. - */ -@kotlin.internal.InlineOnly -public inline fun String.replaceRange(range: IntRange, replacement: CharSequence): String - = (this as CharSequence).replaceRange(range, replacement).toString() - -/** - * Returns a char sequence with content of this char sequence where its part at the given range is removed. - * - * @param startIndex the index of the first character to be removed. - * @param endIndex the index of the first character after the removed part to keep in the string. - * - * [endIndex] is not included in the removed part. - */ -public fun CharSequence.removeRange(startIndex: Int, endIndex: Int): CharSequence { - if (endIndex < startIndex) - throw IndexOutOfBoundsException("End index ($endIndex) is less than start index ($startIndex).") - - if (endIndex == startIndex) - return this.subSequence(0, length) - - val sb = StringBuilder(length - (endIndex - startIndex)) - sb.append(this, 0, startIndex) - sb.append(this, endIndex, length) - return sb -} - -/** - * Removes the part of a string at a given range. - * @param startIndex the index of the first character to be removed. - * @param endIndex the index of the first character after the removed part to keep in the string. - * - * [endIndex] is not included in the removed part. - */ -@kotlin.internal.InlineOnly -public inline fun String.removeRange(startIndex: Int, endIndex: Int): String - = (this as CharSequence).removeRange(startIndex, endIndex).toString() - -/** - * Returns a char sequence with content of this char sequence where its part at the given [range] is removed. - * - * The end index of the [range] is included in the removed part. - */ -public fun CharSequence.removeRange(range: IntRange): CharSequence = removeRange(range.start, range.endInclusive + 1) - -/** - * Removes the part of a string at the given [range]. - * - * The end index of the [range] is included in the removed part. - */ -@kotlin.internal.InlineOnly -public inline fun String.removeRange(range: IntRange): String - = (this as CharSequence).removeRange(range).toString() - -/** - * If this char sequence starts with the given [prefix], returns a new char sequence - * with the prefix removed. Otherwise, returns a new char sequence with the same characters. - */ -public fun CharSequence.removePrefix(prefix: CharSequence): CharSequence { - if (startsWith(prefix)) { - return subSequence(prefix.length, length) - } - return subSequence(0, length) -} - -/** - * If this string starts with the given [prefix], returns a copy of this string - * with the prefix removed. Otherwise, returns this string. - */ -public fun String.removePrefix(prefix: CharSequence): String { - if (startsWith(prefix)) { - return substring(prefix.length) - } - return this -} - -/** - * If this char sequence ends with the given [suffix], returns a new char sequence - * with the suffix removed. Otherwise, returns a new char sequence with the same characters. - */ -public fun CharSequence.removeSuffix(suffix: CharSequence): CharSequence { - if (endsWith(suffix)) { - return subSequence(0, length - suffix.length) - } - return subSequence(0, length) -} - -/** - * If this string ends with the given [suffix], returns a copy of this string - * with the suffix removed. Otherwise, returns this string. - */ -public fun String.removeSuffix(suffix: CharSequence): String { - if (endsWith(suffix)) { - return substring(0, length - suffix.length) - } - return this -} - -/** - * When this char sequence starts with the given [prefix] and ends with the given [suffix], - * returns a new char sequence having both the given [prefix] and [suffix] removed. - * Otherwise returns a new char sequence with the same characters. - */ -public fun CharSequence.removeSurrounding(prefix: CharSequence, suffix: CharSequence): CharSequence { - if ((length >= prefix.length + suffix.length) && startsWith(prefix) && endsWith(suffix)) { - return subSequence(prefix.length, length - suffix.length) - } - return subSequence(0, length) -} - -/** - * Removes from a string both the given [prefix] and [suffix] if and only if - * it starts with the [prefix] and ends with the [suffix]. - * Otherwise returns this string unchanged. - */ -public fun String.removeSurrounding(prefix: CharSequence, suffix: CharSequence): String { - if ((length >= prefix.length + suffix.length) && startsWith(prefix) && endsWith(suffix)) { - return substring(prefix.length, length - suffix.length) - } - return this -} - -/** - * When this char sequence starts with and ends with the given [delimiter], - * returns a new char sequence having this [delimiter] removed both from the start and end. - * Otherwise returns a new char sequence with the same characters. - */ -public fun CharSequence.removeSurrounding(delimiter: CharSequence): CharSequence = removeSurrounding(delimiter, delimiter) - -/** - * Removes the given [delimiter] string from both the start and the end of this string - * if and only if it starts with and ends with the [delimiter]. - * Otherwise returns this string unchanged. - */ -public fun String.removeSurrounding(delimiter: CharSequence): String = removeSurrounding(delimiter, delimiter) - -/** - * Replace part of string before the first occurrence of given delimiter with the [replacement] string. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.replaceBefore(delimiter: Char, replacement: String, missingDelimiterValue: String = this): String { - val index = indexOf(delimiter) - return if (index == -1) missingDelimiterValue else replaceRange(0, index, replacement) -} - -/** - * Replace part of string before the first occurrence of given delimiter with the [replacement] string. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.replaceBefore(delimiter: String, replacement: String, missingDelimiterValue: String = this): String { - val index = indexOf(delimiter) - return if (index == -1) missingDelimiterValue else replaceRange(0, index, replacement) -} - -/** - * Replace part of string after the first occurrence of given delimiter with the [replacement] string. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.replaceAfter(delimiter: Char, replacement: String, missingDelimiterValue: String = this): String { - val index = indexOf(delimiter) - return if (index == -1) missingDelimiterValue else replaceRange(index + 1, length, replacement) -} - -/** - * Replace part of string after the first occurrence of given delimiter with the [replacement] string. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.replaceAfter(delimiter: String, replacement: String, missingDelimiterValue: String = this): String { - val index = indexOf(delimiter) - return if (index == -1) missingDelimiterValue else replaceRange(index + delimiter.length, length, replacement) -} - -/** - * Replace part of string after the last occurrence of given delimiter with the [replacement] string. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.replaceAfterLast(delimiter: String, replacement: String, missingDelimiterValue: String = this): String { - val index = lastIndexOf(delimiter) - return if (index == -1) missingDelimiterValue else replaceRange(index + delimiter.length, length, replacement) -} - -/** - * Replace part of string after the last occurrence of given delimiter with the [replacement] string. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.replaceAfterLast(delimiter: Char, replacement: String, missingDelimiterValue: String = this): String { - val index = lastIndexOf(delimiter) - return if (index == -1) missingDelimiterValue else replaceRange(index + 1, length, replacement) -} - -/** - * Replace part of string before the last occurrence of given delimiter with the [replacement] string. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.replaceBeforeLast(delimiter: Char, replacement: String, missingDelimiterValue: String = this): String { - val index = lastIndexOf(delimiter) - return if (index == -1) missingDelimiterValue else replaceRange(0, index, replacement) -} - -/** - * Replace part of string before the last occurrence of given delimiter with the [replacement] string. - * If the string does not contain the delimiter, returns [missingDelimiterValue] which defaults to the original string. - */ -public fun String.replaceBeforeLast(delimiter: String, replacement: String, missingDelimiterValue: String = this): String { - val index = lastIndexOf(delimiter) - return if (index == -1) missingDelimiterValue else replaceRange(0, index, replacement) -} - -/** - * Returns a new string obtained by replacing each substring of this char sequence that matches the given regular expression - * with the given [replacement]. - * - * The [replacement] can consist of any combination of literal text and $-substitutions. To treat the replacement string - * literally escape it with the [kotlin.text.Regex.Companion.escapeReplacement] method. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.replace(regex: Regex, replacement: String): String = regex.replace(this, replacement) - -/** - * Returns a new string obtained by replacing each substring of this char sequence that matches the given regular expression - * with the result of the given function [transform] that takes [MatchResult] and returns a string to be used as a - * replacement for that match. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.replace(regex: Regex, noinline transform: (MatchResult) -> CharSequence): String = regex.replace(this, transform) - -/** - * Replaces the first occurrence of the given regular expression [regex] in this char sequence with specified [replacement] expression. - * - * @param replacement A replacement expression that can include substitutions. See [Regex.replaceFirst] for details. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.replaceFirst(regex: Regex, replacement: String): String = regex.replaceFirst(this, replacement) - - -/** - * Returns `true` if this char sequence matches the given regular expression. - */ -@kotlin.internal.InlineOnly -public infix inline fun CharSequence.matches(regex: Regex): Boolean = regex.matches(this) - -/** - * Implementation of [regionMatches] for CharSequences. - * Invoked when it's already known that arguments are not Strings, so that no additional type checks are performed. - */ -internal fun CharSequence.regionMatchesImpl(thisOffset: Int, other: CharSequence, otherOffset: Int, length: Int, ignoreCase: Boolean): Boolean { - if ((otherOffset < 0) || (thisOffset < 0) || (thisOffset > this.length - length) - || (otherOffset > other.length - length)) { - return false - } - - for (index in 0..length-1) { - if (!this[thisOffset + index].equals(other[otherOffset + index], ignoreCase)) - return false - } - return true -} - -/** - * Returns `true` if this char sequence starts with the specified character. - */ -public fun CharSequence.startsWith(char: Char, ignoreCase: Boolean = false): Boolean = - this.length > 0 && this[0].equals(char, ignoreCase) - -/** - * Returns `true` if this char sequence ends with the specified character. - */ -public fun CharSequence.endsWith(char: Char, ignoreCase: Boolean = false): Boolean = - this.length > 0 && this[lastIndex].equals(char, ignoreCase) - -/** - * Returns `true` if this char sequence starts with the specified prefix. - */ -public fun CharSequence.startsWith(prefix: CharSequence, ignoreCase: Boolean = false): Boolean { - if (!ignoreCase && this is String && prefix is String) - return this.startsWith(prefix) - else - return regionMatchesImpl(0, prefix, 0, prefix.length, ignoreCase) -} - -/** - * Returns `true` if a substring of this char sequence starting at the specified offset [startIndex] starts with the specified prefix. - */ -public fun CharSequence.startsWith(prefix: CharSequence, startIndex: Int, ignoreCase: Boolean = false): Boolean { - if (!ignoreCase && this is String && prefix is String) - return this.startsWith(prefix, startIndex) - else - return regionMatchesImpl(startIndex, prefix, 0, prefix.length, ignoreCase) -} - -/** - * Returns `true` if this char sequence ends with the specified suffix. - */ -public fun CharSequence.endsWith(suffix: CharSequence, ignoreCase: Boolean = false): Boolean { - if (!ignoreCase && this is String && suffix is String) - return this.endsWith(suffix) - else - return regionMatchesImpl(length - suffix.length, suffix, 0, suffix.length, ignoreCase) -} - - -// common prefix and suffix - -/** - * Returns the longest string `prefix` such that this char sequence and [other] char sequence both start with this prefix, - * taking care not to split surrogate pairs. - * If this and [other] have no common prefix, returns the empty string. - - * @param ignoreCase `true` to ignore character case when matching a character. By default `false`. - */ -public fun CharSequence.commonPrefixWith(other: CharSequence, ignoreCase: Boolean = false): String { - val shortestLength = minOf(this.length, other.length) - - var i = 0 - while (i < shortestLength && this[i].equals(other[i], ignoreCase = ignoreCase)) { - i++ - } - if (this.hasSurrogatePairAt(i - 1) || other.hasSurrogatePairAt(i - 1)) { - i-- - } - return subSequence(0, i).toString() -} - -/** - * Returns the longest string `suffix` such that this char sequence and [other] char sequence both end with this suffix, - * taking care not to split surrogate pairs. - * If this and [other] have no common suffix, returns the empty string. - - * @param ignoreCase `true` to ignore character case when matching a character. By default `false`. - */ -public fun CharSequence.commonSuffixWith(other: CharSequence, ignoreCase: Boolean = false): String { - val thisLength = this.length - val otherLength = other.length - val shortestLength = minOf(thisLength, otherLength) - - var i = 0 - while (i < shortestLength && this[thisLength - i - 1].equals(other[otherLength - i - 1], ignoreCase = ignoreCase)) { - i++ - } - if (this.hasSurrogatePairAt(thisLength - i - 1) || other.hasSurrogatePairAt(otherLength - i - 1)) { - i-- - } - return subSequence(thisLength - i, thisLength).toString() -} - - -// indexOfAny() - -private fun CharSequence.findAnyOf(chars: CharArray, startIndex: Int, ignoreCase: Boolean, last: Boolean): Pair? { - if (!ignoreCase && chars.size == 1 && this is String) { - val char = chars.single() - val index = if (!last) nativeIndexOf(char, startIndex) else nativeLastIndexOf(char, startIndex) - return if (index < 0) null else index to char - } - - val indices = if (!last) startIndex.coerceAtLeast(0)..lastIndex else startIndex.coerceAtMost(lastIndex) downTo 0 - for (index in indices) { - val charAtIndex = get(index) - val matchingCharIndex = chars.indexOfFirst { it.equals(charAtIndex, ignoreCase) } - if (matchingCharIndex >= 0) - return index to chars[matchingCharIndex] - } - - return null -} - -/** - * Finds the index of the first occurrence of any of the specified [chars] in this char sequence, - * starting from the specified [startIndex] and optionally ignoring the case. - * - * @param ignoreCase `true` to ignore character case when matching a character. By default `false`. - * @returns An index of the first occurrence of matched character from [chars] or -1 if none of [chars] are found. - * - */ -public fun CharSequence.indexOfAny(chars: CharArray, startIndex: Int = 0, ignoreCase: Boolean = false): Int = - findAnyOf(chars, startIndex, ignoreCase, last = false)?.first ?: -1 - -/** - * Finds the index of the last occurrence of any of the specified [chars] in this char sequence, - * starting from the specified [startIndex] and optionally ignoring the case. - * - * @param startIndex The index of character to start searching at. The search proceeds backward toward the beginning of the string. - * @param ignoreCase `true` to ignore character case when matching a character. By default `false`. - * @returns An index of the last occurrence of matched character from [chars] or -1 if none of [chars] are found. - * - */ -public fun CharSequence.lastIndexOfAny(chars: CharArray, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int = - findAnyOf(chars, startIndex, ignoreCase, last = true)?.first ?: -1 - - -private fun CharSequence.indexOf(other: CharSequence, startIndex: Int, endIndex: Int, ignoreCase: Boolean, last: Boolean = false): Int { - val indices = if (!last) - startIndex.coerceAtLeast(0)..endIndex.coerceAtMost(length) - else - startIndex.coerceAtMost(lastIndex) downTo endIndex.coerceAtLeast(0) - - if (this is String && other is String) { // smart cast - for (index in indices) { - if (other.regionMatches(0, this, index, other.length, ignoreCase)) - return index - } - } else { - for (index in indices) { - if (other.regionMatchesImpl(0, this, index, other.length, ignoreCase)) - return index - } - } - return -1 -} - -private fun CharSequence.findAnyOf(strings: Collection, startIndex: Int, ignoreCase: Boolean, last: Boolean): Pair? { - if (!ignoreCase && strings.size == 1) { - val string = strings.single() - val index = if (!last) indexOf(string, startIndex) else lastIndexOf(string, startIndex) - return if (index < 0) null else index to string - } - - val indices = if (!last) startIndex.coerceAtLeast(0)..length else startIndex.coerceAtMost(lastIndex) downTo 0 - - if (this is String) { - for (index in indices) { - val matchingString = strings.firstOrNull { it.regionMatches(0, this, index, it.length, ignoreCase) } - if (matchingString != null) - return index to matchingString - } - } else { - for (index in indices) { - val matchingString = strings.firstOrNull { it.regionMatchesImpl(0, this, index, it.length, ignoreCase) } - if (matchingString != null) - return index to matchingString - } - } - - return null -} - -/** - * Finds the first occurrence of any of the specified [strings] in this char sequence, - * starting from the specified [startIndex] and optionally ignoring the case. - * - * @param ignoreCase `true` to ignore character case when matching a string. By default `false`. - * @returns A pair of an index of the first occurrence of matched string from [strings] and the string matched - * or `null` if none of [strings] are found. - * - * To avoid ambiguous results when strings in [strings] have characters in common, this method proceeds from - * the beginning to the end of this string, and finds at each position the first element in [strings] - * that matches this string at that position. - */ -public fun CharSequence.findAnyOf(strings: Collection, startIndex: Int = 0, ignoreCase: Boolean = false): Pair? = - findAnyOf(strings, startIndex, ignoreCase, last = false) - -/** - * Finds the last occurrence of any of the specified [strings] in this char sequence, - * starting from the specified [startIndex] and optionally ignoring the case. - * - * @param startIndex The index of character to start searching at. The search proceeds backward toward the beginning of the string. - * @param ignoreCase `true` to ignore character case when matching a string. By default `false`. - * @returns A pair of an index of the last occurrence of matched string from [strings] and the string matched or `null` if none of [strings] are found. - * - * To avoid ambiguous results when strings in [strings] have characters in common, this method proceeds from - * the end toward the beginning of this string, and finds at each position the first element in [strings] - * that matches this string at that position. - */ -public fun CharSequence.findLastAnyOf(strings: Collection, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Pair? = - findAnyOf(strings, startIndex, ignoreCase, last = true) - -/** - * Finds the index of the first occurrence of any of the specified [strings] in this char sequence, - * starting from the specified [startIndex] and optionally ignoring the case. - * - * @param ignoreCase `true` to ignore character case when matching a string. By default `false`. - * @returns An index of the first occurrence of matched string from [strings] or -1 if none of [strings] are found. - * - * To avoid ambiguous results when strings in [strings] have characters in common, this method proceeds from - * the beginning to the end of this string, and finds at each position the first element in [strings] - * that matches this string at that position. - */ -public fun CharSequence.indexOfAny(strings: Collection, startIndex: Int = 0, ignoreCase: Boolean = false): Int = - findAnyOf(strings, startIndex, ignoreCase, last = false)?.first ?: -1 - -/** - * Finds the index of the last occurrence of any of the specified [strings] in this char sequence, - * starting from the specified [startIndex] and optionally ignoring the case. - * - * @param startIndex The index of character to start searching at. The search proceeds backward toward the beginning of the string. - * @param ignoreCase `true` to ignore character case when matching a string. By default `false`. - * @returns An index of the last occurrence of matched string from [strings] or -1 if none of [strings] are found. - * - * To avoid ambiguous results when strings in [strings] have characters in common, this method proceeds from - * the end toward the beginning of this string, and finds at each position the first element in [strings] - * that matches this string at that position. - */ -public fun CharSequence.lastIndexOfAny(strings: Collection, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int = - findAnyOf(strings, startIndex, ignoreCase, last = true)?.first ?: -1 - - -// indexOf - -/** - * Returns the index within this string of the first occurrence of the specified character, starting from the specified [startIndex]. - * - * @param ignoreCase `true` to ignore character case when matching a character. By default `false`. - * @returns An index of the first occurrence of [char] or -1 if none is found. - */ -public fun CharSequence.indexOf(char: Char, startIndex: Int = 0, ignoreCase: Boolean = false): Int { - return if (ignoreCase || this !is String) - indexOfAny(charArrayOf(char), startIndex, ignoreCase) - else - nativeIndexOf(char, startIndex) -} - -/** - * Returns the index within this char sequence of the first occurrence of the specified [string], - * starting from the specified [startIndex]. - * - * @param ignoreCase `true` to ignore character case when matching a string. By default `false`. - * @returns An index of the first occurrence of [string] or `-1` if none is found. - */ -public fun CharSequence.indexOf(string: String, startIndex: Int = 0, ignoreCase: Boolean = false): Int { - return if (ignoreCase || this !is String) - indexOf(string, startIndex, length, ignoreCase) - else - nativeIndexOf(string, startIndex) -} - -/** - * Returns the index within this char sequence of the last occurrence of the specified character, - * starting from the specified [startIndex]. - * - * @param startIndex The index of character to start searching at. The search proceeds backward toward the beginning of the string. - * @param ignoreCase `true` to ignore character case when matching a character. By default `false`. - * @returns An index of the first occurrence of [char] or -1 if none is found. - */ -public fun CharSequence.lastIndexOf(char: Char, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int { - return if (ignoreCase || this !is String) - lastIndexOfAny(charArrayOf(char), startIndex, ignoreCase) - else - nativeLastIndexOf(char, startIndex) -} - -/** - * Returns the index within this char sequence of the last occurrence of the specified [string], - * starting from the specified [startIndex]. - * - * @param startIndex The index of character to start searching at. The search proceeds backward toward the beginning of the string. - * @param ignoreCase `true` to ignore character case when matching a string. By default `false`. - * @returns An index of the first occurrence of [string] or -1 if none is found. - */ -public fun CharSequence.lastIndexOf(string: String, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int { - return if (ignoreCase || this !is String) - indexOf(string, startIndex, 0, ignoreCase, last = true) - else - nativeLastIndexOf(string, startIndex) -} - -/** - * Returns `true` if this char sequence contains the specified [other] sequence of characters as a substring. - * - * @param ignoreCase `true` to ignore character case when comparing strings. By default `false`. - */ -@Suppress("INAPPLICABLE_OPERATOR_MODIFIER") -public operator fun CharSequence.contains(other: CharSequence, ignoreCase: Boolean = false): Boolean = - if (other is String) - indexOf(other, ignoreCase = ignoreCase) >= 0 - else - indexOf(other, 0, length, ignoreCase) >= 0 - - - -/** - * Returns `true` if this char sequence contains the specified character [char]. - * - * @param ignoreCase `true` to ignore character case when comparing characters. By default `false`. - */ -@Suppress("INAPPLICABLE_OPERATOR_MODIFIER") -public operator fun CharSequence.contains(char: Char, ignoreCase: Boolean = false): Boolean = - indexOf(char, ignoreCase = ignoreCase) >= 0 - -/** - * Returns `true` if this char sequence contains at least one match of the specified regular expression [regex]. - */ -@kotlin.internal.InlineOnly -public inline operator fun CharSequence.contains(regex: Regex): Boolean = regex.containsMatchIn(this) - - -// rangesDelimitedBy - - -private class DelimitedRangesSequence(private val input: CharSequence, private val startIndex: Int, private val limit: Int, private val getNextMatch: CharSequence.(Int) -> Pair?): Sequence { - - override fun iterator(): Iterator = object : Iterator { - var nextState: Int = -1 // -1 for unknown, 0 for done, 1 for continue - var currentStartIndex: Int = startIndex.coerceIn(0, input.length) - var nextSearchIndex: Int = currentStartIndex - var nextItem: IntRange? = null - var counter: Int = 0 - - private fun calcNext() { - if (nextSearchIndex < 0) { - nextState = 0 - nextItem = null - } - else { - if (limit > 0 && ++counter >= limit || nextSearchIndex > input.length) { - nextItem = currentStartIndex..input.lastIndex - nextSearchIndex = -1 - } - else { - val match = input.getNextMatch(nextSearchIndex) - if (match == null) { - nextItem = currentStartIndex..input.lastIndex - nextSearchIndex = -1 - } - else { - val (index,length) = match - nextItem = currentStartIndex..index-1 - currentStartIndex = index + length - nextSearchIndex = currentStartIndex + if (length == 0) 1 else 0 - } - } - nextState = 1 - } - } - - override fun next(): IntRange { - if (nextState == -1) - calcNext() - if (nextState == 0) - throw NoSuchElementException() - val result = nextItem as IntRange - // Clean next to avoid keeping reference on yielded instance - nextItem = null - nextState = -1 - return result - } - - override fun hasNext(): Boolean { - if (nextState == -1) - calcNext() - return nextState == 1 - } - } -} - -/** - * Returns a sequence of index ranges of substrings in this char sequence around occurrences of the specified [delimiters]. - * - * @param delimiters One or more characters to be used as delimiters. - * @param startIndex The index to start searching delimiters from. - * No range having its start value less than [startIndex] is returned. - * [startIndex] is coerced to be non-negative and not greater than length of this string. - * @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`. - * @param limit The maximum number of substrings to return. Zero by default means no limit is set. - */ -private fun CharSequence.rangesDelimitedBy(delimiters: CharArray, startIndex: Int = 0, ignoreCase: Boolean = false, limit: Int = 0): Sequence { - require(limit >= 0, { "Limit must be non-negative, but was $limit." }) - - return DelimitedRangesSequence(this, startIndex, limit, { index -> findAnyOf(delimiters, index, ignoreCase = ignoreCase, last = false)?.let { it.first to 1 } }) -} - - -/** - * Returns a sequence of index ranges of substrings in this char sequence around occurrences of the specified [delimiters]. - * - * @param delimiters One or more strings to be used as delimiters. - * @param startIndex The index to start searching delimiters from. - * No range having its start value less than [startIndex] is returned. - * [startIndex] is coerced to be non-negative and not greater than length of this string. - * @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`. - * @param limit The maximum number of substrings to return. Zero by default means no limit is set. - * - * To avoid ambiguous results when strings in [delimiters] have characters in common, this method proceeds from - * the beginning to the end of this string, and finds at each position the first element in [delimiters] - * that matches this string at that position. - */ -private fun CharSequence.rangesDelimitedBy(delimiters: Array, startIndex: Int = 0, ignoreCase: Boolean = false, limit: Int = 0): Sequence { - require(limit >= 0, { "Limit must be non-negative, but was $limit." } ) - val delimitersList = delimiters.asList() - - return DelimitedRangesSequence(this, startIndex, limit, { index -> findAnyOf(delimitersList, index, ignoreCase = ignoreCase, last = false)?.let { it.first to it.second.length } }) - -} - - -// split - -/** - * Splits this char sequence to a sequence of strings around occurrences of the specified [delimiters]. - * - * @param delimiters One or more strings to be used as delimiters. - * @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`. - * @param limit The maximum number of substrings to return. Zero by default means no limit is set. - * - * To avoid ambiguous results when strings in [delimiters] have characters in common, this method proceeds from - * the beginning to the end of this string, and finds at each position the first element in [delimiters] - * that matches this string at that position. - */ -public fun CharSequence.splitToSequence(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): Sequence = - rangesDelimitedBy(delimiters, ignoreCase = ignoreCase, limit = limit).map { substring(it) } - -/** - * Splits this char sequence to a list of strings around occurrences of the specified [delimiters]. - * - * @param delimiters One or more strings to be used as delimiters. - * @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`. - * @param limit The maximum number of substrings to return. Zero by default means no limit is set. - * - * To avoid ambiguous results when strings in [delimiters] have characters in common, this method proceeds from - * the beginning to the end of this string, and matches at each position the first element in [delimiters] - * that is equal to a delimiter in this instance at that position. - */ -public fun CharSequence.split(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): List = - rangesDelimitedBy(delimiters, ignoreCase = ignoreCase, limit = limit).asIterable().map { substring(it) } - -/** - * Splits this char sequence to a sequence of strings around occurrences of the specified [delimiters]. - * - * @param delimiters One or more characters to be used as delimiters. - * @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`. - * @param limit The maximum number of substrings to return. - */ -public fun CharSequence.splitToSequence(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): Sequence = - rangesDelimitedBy(delimiters, ignoreCase = ignoreCase, limit = limit).map { substring(it) } - -/** - * Splits this char sequence to a list of strings around occurrences of the specified [delimiters]. - * - * @param delimiters One or more characters to be used as delimiters. - * @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`. - * @param limit The maximum number of substrings to return. - */ -public fun CharSequence.split(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): List = - rangesDelimitedBy(delimiters, ignoreCase = ignoreCase, limit = limit).asIterable().map { substring(it) } - -/** - * Splits this char sequence around matches of the given regular expression. - * - * @param limit Non-negative value specifying the maximum number of substrings to return. - * Zero by default means no limit is set. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.split(regex: Regex, limit: Int = 0): List = regex.split(this, limit) - -/** - * Splits this char sequence to a sequence of lines delimited by any of the following character sequences: CRLF, LF or CR. - */ -public fun CharSequence.lineSequence(): Sequence = splitToSequence("\r\n", "\n", "\r") - -/** - * * Splits this char sequence to a list of lines delimited by any of the following character sequences: CRLF, LF or CR. - */ -public fun CharSequence.lines(): List = lineSequence().toList() - -// From _Strings.kt. - -/** - * Returns a character at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this char sequence. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.elementAt(index: Int): Char { - return get(index) -} - -/** - * Returns a character at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this char sequence. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.elementAtOrElse(index: Int, defaultValue: (Int) -> Char): Char { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns a character at the given [index] or `null` if the [index] is out of bounds of this char sequence. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.elementAtOrNull(index: Int): Char? { - return this.getOrNull(index) -} - -/** - * Returns the first character matching the given [predicate], or `null` if no such character was found. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.find(predicate: (Char) -> Boolean): Char? { - return firstOrNull(predicate) -} - -/** - * Returns the last character matching the given [predicate], or `null` if no such character was found. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.findLast(predicate: (Char) -> Boolean): Char? { - return lastOrNull(predicate) -} - -/** - * Returns first character. - * @throws [NoSuchElementException] if the char sequence is empty. - */ -public fun CharSequence.first(): Char { - if (isEmpty()) - throw NoSuchElementException("Char sequence is empty.") - return this[0] -} - -/** - * Returns the first character matching the given [predicate]. - * @throws [NoSuchElementException] if no such character is found. - */ -public inline fun CharSequence.first(predicate: (Char) -> Boolean): Char { - for (element in this) if (predicate(element)) return element - throw NoSuchElementException("Char sequence contains no character matching the predicate.") -} - -/** - * Returns the first character, or `null` if the char sequence is empty. - */ -public fun CharSequence.firstOrNull(): Char? { - return if (isEmpty()) null else this[0] -} - -/** - * Returns the first character matching the given [predicate], or `null` if character was not found. - */ -public inline fun CharSequence.firstOrNull(predicate: (Char) -> Boolean): Char? { - for (element in this) if (predicate(element)) return element - return null -} - -/** - * Returns a character at the given [index] or the result of calling the [defaultValue] function if the [index] is out of bounds of this char sequence. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.getOrElse(index: Int, defaultValue: (Int) -> Char): Char { - return if (index >= 0 && index <= lastIndex) get(index) else defaultValue(index) -} - -/** - * Returns a character at the given [index] or `null` if the [index] is out of bounds of this char sequence. - */ -public fun CharSequence.getOrNull(index: Int): Char? { - return if (index >= 0 && index <= lastIndex) get(index) else null -} - -/** - * Returns index of the first character matching the given [predicate], or -1 if the char sequence does not contain such character. - */ -public inline fun CharSequence.indexOfFirst(predicate: (Char) -> Boolean): Int { - for (index in indices) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns index of the last character matching the given [predicate], or -1 if the char sequence does not contain such character. - */ -public inline fun CharSequence.indexOfLast(predicate: (Char) -> Boolean): Int { - for (index in indices.reversed()) { - if (predicate(this[index])) { - return index - } - } - return -1 -} - -/** - * Returns the last character. - * @throws [NoSuchElementException] if the char sequence is empty. - */ -public fun CharSequence.last(): Char { - if (isEmpty()) - throw NoSuchElementException("Char sequence is empty.") - return this[lastIndex] -} - -/** - * Returns the last character matching the given [predicate]. - * @throws [NoSuchElementException] if no such character is found. - */ -public inline fun CharSequence.last(predicate: (Char) -> Boolean): Char { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - throw NoSuchElementException("Char sequence contains no character matching the predicate.") -} - -/** - * Returns the last character, or `null` if the char sequence is empty. - */ -public fun CharSequence.lastOrNull(): Char? { - return if (isEmpty()) null else this[length - 1] -} - -/** - * Returns the last character matching the given [predicate], or `null` if no such character was found. - */ -public inline fun CharSequence.lastOrNull(predicate: (Char) -> Boolean): Char? { - for (index in this.indices.reversed()) { - val element = this[index] - if (predicate(element)) return element - } - return null -} - -/** - * Returns the single character, or throws an exception if the char sequence is empty or has more than one character. - */ -public fun CharSequence.single(): Char { - return when (length) { - 0 -> throw NoSuchElementException("Char sequence is empty.") - 1 -> this[0] - else -> throw IllegalArgumentException("Char sequence has more than one element.") - } -} - -/** - * Returns the single character matching the given [predicate], or throws exception if there is no or more than one matching character. - */ -public inline fun CharSequence.single(predicate: (Char) -> Boolean): Char { - var single: Char? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) throw IllegalArgumentException("Char sequence contains more than one matching element.") - single = element - found = true - } - } - if (!found) throw NoSuchElementException("Char sequence contains no character matching the predicate.") - return single as Char -} - -/** - * Returns single character, or `null` if the char sequence is empty or has more than one character. - */ -public fun CharSequence.singleOrNull(): Char? { - return if (length == 1) this[0] else null -} - -/** - * Returns the single character matching the given [predicate], or `null` if character was not found or more than one character was found. - */ -public inline fun CharSequence.singleOrNull(predicate: (Char) -> Boolean): Char? { - var single: Char? = null - var found = false - for (element in this) { - if (predicate(element)) { - if (found) return null - single = element - found = true - } - } - if (!found) return null - return single -} - -/** - * Returns a subsequence of this char sequence with the first [n] characters removed. - */ -public fun CharSequence.drop(n: Int): CharSequence { - require(n >= 0) { "Requested character count $n is less than zero." } - return subSequence(n.coerceAtMost(length), length) -} - -/** - * Returns a string with the first [n] characters removed. - */ -public fun String.drop(n: Int): String { - require(n >= 0) { "Requested character count $n is less than zero." } - return substring(n.coerceAtMost(length)) -} - -/** - * Returns a subsequence of this char sequence with the last [n] characters removed. - */ -public fun CharSequence.dropLast(n: Int): CharSequence { - require(n >= 0) { "Requested character count $n is less than zero." } - return take((length - n).coerceAtLeast(0)) -} - -/** - * Returns a string with the last [n] characters removed. - */ -public fun String.dropLast(n: Int): String { - require(n >= 0) { "Requested character count $n is less than zero." } - return take((length - n).coerceAtLeast(0)) -} - -/** - * Returns a subsequence of this char sequence containing all characters except last characters that satisfy the given [predicate]. - */ -public inline fun CharSequence.dropLastWhile(predicate: (Char) -> Boolean): CharSequence { - for (index in this.indices.reversed()) - if (!predicate(this[index])) - return subSequence(0, index + 1) - return "" -} - -/** - * Returns a string containing all characters except last characters that satisfy the given [predicate]. - */ -public inline fun String.dropLastWhile(predicate: (Char) -> Boolean): String { - for (index in this.indices.reversed()) - if (!predicate(this[index])) - return substring(0, index + 1) - return "" -} - -/** - * Returns a subsequence of this char sequence containing all characters except first characters that satisfy the given [predicate]. - */ -public inline fun CharSequence.dropWhile(predicate: (Char) -> Boolean): CharSequence { - for (index in this.indices) - if (!predicate(this[index])) - return subSequence(index, length) - return "" -} - -/** - * Returns a string containing all characters except first characters that satisfy the given [predicate]. - */ -public inline fun String.dropWhile(predicate: (Char) -> Boolean): String { - for (index in this.indices) - if (!predicate(this[index])) - return substring(index) - return "" -} - -/** - * Returns a char sequence containing only those characters from the original char sequence that match the given [predicate]. - */ -public inline fun CharSequence.filter(predicate: (Char) -> Boolean): CharSequence { - return filterTo(StringBuilder(), predicate) -} - -/** - * Returns a string containing only those characters from the original string that match the given [predicate]. - */ -public inline fun String.filter(predicate: (Char) -> Boolean): String { - return filterTo(StringBuilder(), predicate).toString() -} - -/** - * Returns a char sequence containing only those characters from the original char sequence that match the given [predicate]. - * @param [predicate] function that takes the index of a character and the character itself - * and returns the result of predicate evaluation on the character. - */ -public inline fun CharSequence.filterIndexed(predicate: (index: Int, Char) -> Boolean): CharSequence { - return filterIndexedTo(StringBuilder(), predicate) -} - -/** - * Returns a string containing only those characters from the original string that match the given [predicate]. - * @param [predicate] function that takes the index of a character and the character itself - * and returns the result of predicate evaluation on the character. - */ -public inline fun String.filterIndexed(predicate: (index: Int, Char) -> Boolean): String { - return filterIndexedTo(StringBuilder(), predicate).toString() -} - -/** - * Appends all characters matching the given [predicate] to the given [destination]. - * @param [predicate] function that takes the index of a character and the character itself - * and returns the result of predicate evaluation on the character. - */ -public inline fun CharSequence.filterIndexedTo(destination: C, predicate: (index: Int, Char) -> Boolean): C { - forEachIndexed { index, element -> - if (predicate(index, element)) destination.append(element) - } - return destination -} - -/** - * Returns a char sequence containing only those characters from the original char sequence that do not match the given [predicate]. - */ -public inline fun CharSequence.filterNot(predicate: (Char) -> Boolean): CharSequence { - return filterNotTo(StringBuilder(), predicate) -} - -/** - * Returns a string containing only those characters from the original string that do not match the given [predicate]. - */ -public inline fun String.filterNot(predicate: (Char) -> Boolean): String { - return filterNotTo(StringBuilder(), predicate).toString() -} - -/** - * Appends all characters not matching the given [predicate] to the given [destination]. - */ -public inline fun CharSequence.filterNotTo(destination: C, predicate: (Char) -> Boolean): C { - for (element in this) if (!predicate(element)) destination.append(element) - return destination -} - -/** - * Appends all characters matching the given [predicate] to the given [destination]. - */ -public inline fun CharSequence.filterTo(destination: C, predicate: (Char) -> Boolean): C { - for (index in 0..length - 1) { - val element = get(index) - if (predicate(element)) destination.append(element) - } - return destination -} - -/** - * Returns a char sequence containing characters of the original char sequence at the specified range of [indices]. - */ -public fun CharSequence.slice(indices: IntRange): CharSequence { - if (indices.isEmpty()) return "" - return subSequence(indices) -} - -/** - * Returns a string containing characters of the original string at the specified range of [indices]. - */ -public fun String.slice(indices: IntRange): String { - if (indices.isEmpty()) return "" - return substring(indices) -} - -/** - * Returns a char sequence containing characters of the original char sequence at specified [indices]. - */ -public fun CharSequence.slice(indices: Iterable): CharSequence { - val size = indices.collectionSizeOrDefault(10) - if (size == 0) return "" - val result = StringBuilder(size) - for (i in indices) { - result.append(get(i)) - } - return result -} - -/** - * Returns a string containing characters of the original string at specified [indices]. - */ -@kotlin.internal.InlineOnly -public inline fun String.slice(indices: Iterable): String { - return (this as CharSequence).slice(indices).toString() -} - -/** - * Returns a subsequence of this char sequence containing the first [n] characters from this char sequence, or the entire char sequence if this char sequence is shorter. - */ -public fun CharSequence.take(n: Int): CharSequence { - require(n >= 0) { "Requested character count $n is less than zero." } - return subSequence(0, n.coerceAtMost(length)) -} - -/** - * Returns a string containing the first [n] characters from this string, or the entire string if this string is shorter. - */ -public fun String.take(n: Int): String { - require(n >= 0) { "Requested character count $n is less than zero." } - return substring(0, n.coerceAtMost(length)) -} - -/** - * Returns a subsequence of this char sequence containing the last [n] characters from this char sequence, or the entire char sequence if this char sequence is shorter. - */ -public fun CharSequence.takeLast(n: Int): CharSequence { - require(n >= 0) { "Requested character count $n is less than zero." } - val length = length - return subSequence(length - n.coerceAtMost(length), length) -} - -/** - * Returns a string containing the last [n] characters from this string, or the entire string if this string is shorter. - */ -public fun String.takeLast(n: Int): String { - require(n >= 0) { "Requested character count $n is less than zero." } - val length = length - return substring(length - n.coerceAtMost(length)) -} - -/** - * Returns a subsequence of this char sequence containing last characters that satisfy the given [predicate]. - */ -public inline fun CharSequence.takeLastWhile(predicate: (Char) -> Boolean): CharSequence { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return subSequence(index + 1, length) - } - } - return subSequence(0, length) -} - -/** - * Returns a string containing last characters that satisfy the given [predicate]. - */ -public inline fun String.takeLastWhile(predicate: (Char) -> Boolean): String { - for (index in lastIndex downTo 0) { - if (!predicate(this[index])) { - return substring(index + 1) - } - } - return this -} - -/** - * Returns a subsequence of this char sequence containing the first characters that satisfy the given [predicate]. - */ -public inline fun CharSequence.takeWhile(predicate: (Char) -> Boolean): CharSequence { - for (index in 0..length - 1) - if (!predicate(get(index))) { - return subSequence(0, index) - } - return subSequence(0, length) -} - -/** - * Returns a string containing the first characters that satisfy the given [predicate]. - */ -public inline fun String.takeWhile(predicate: (Char) -> Boolean): String { - for (index in 0..length - 1) - if (!predicate(get(index))) { - return substring(0, index) - } - return this -} - -/** - * Returns a char sequence with characters in reversed order. - */ -public fun CharSequence.reversed(): CharSequence { - return StringBuilder(this).reverse() -} - -/** - * Returns a string with characters in reversed order. - */ -@kotlin.internal.InlineOnly -public inline fun String.reversed(): String { - return (this as CharSequence).reversed().toString() -} - -/** - * Returns a [Map] containing key-value pairs provided by [transform] function - * applied to characters of the given char sequence. - * - * If any of two pairs would have the same key the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original char sequence. - */ -public inline fun CharSequence.associate(transform: (Char) -> Pair): Map { - val capacity = mapCapacity(length).coerceAtLeast(16) - return associateTo(LinkedHashMap(capacity), transform) -} - -/** - * Returns a [Map] containing the characters from the given char sequence indexed by the key - * returned from [keySelector] function applied to each character. - * - * If any two characters would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original char sequence. - */ -public inline fun CharSequence.associateBy(keySelector: (Char) -> K): Map { - val capacity = mapCapacity(length).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector) -} - -/** - * Returns a [Map] containing the values provided by [valueTransform] and indexed by [keySelector] functions applied to characters of the given char sequence. - * - * If any two characters would have the same key returned by [keySelector] the last one gets added to the map. - * - * The returned map preserves the entry iteration order of the original char sequence. - */ -public inline fun CharSequence.associateBy(keySelector: (Char) -> K, valueTransform: (Char) -> V): Map { - val capacity = mapCapacity(length).coerceAtLeast(16) - return associateByTo(LinkedHashMap(capacity), keySelector, valueTransform) -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function applied to each character of the given char sequence - * and value is the character itself. - * - * If any two characters would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > CharSequence.associateByTo(destination: M, keySelector: (Char) -> K): M { - for (element in this) { - destination.put(keySelector(element), element) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs, - * where key is provided by the [keySelector] function and - * and value is provided by the [valueTransform] function applied to characters of the given char sequence. - * - * If any two characters would have the same key returned by [keySelector] the last one gets added to the map. - */ -public inline fun > CharSequence.associateByTo(destination: M, keySelector: (Char) -> K, valueTransform: (Char) -> V): M { - for (element in this) { - destination.put(keySelector(element), valueTransform(element)) - } - return destination -} - -/** - * Populates and returns the [destination] mutable map with key-value pairs - * provided by [transform] function applied to each character of the given char sequence. - * - * If any of two pairs would have the same key the last one gets added to the map. - */ -public inline fun > CharSequence.associateTo(destination: M, transform: (Char) -> Pair): M { - for (element in this) { - destination += transform(element) - } - return destination -} - -/** - * Appends all characters to the given [destination] collection. - */ -public fun > CharSequence.toCollection(destination: C): C { - for (item in this) { - destination.add(item) - } - return destination -} - -/** - * Returns a [HashSet] of all characters. - */ -public fun CharSequence.toHashSet(): HashSet { - return toCollection(HashSet(mapCapacity(length))) -} - -/** - * Returns a [List] containing all characters. - */ -public fun CharSequence.toList(): List { - return when (length) { - 0 -> emptyList() - 1 -> listOf(this[0]) - else -> this.toMutableList() - } -} - -/** - * Returns a [MutableList] filled with all characters of this char sequence. - */ -public fun CharSequence.toMutableList(): MutableList { - return toCollection(ArrayList(length)) -} - -/** - * Returns a [Set] of all characters. - * - * The returned set preserves the element iteration order of the original char sequence. - */ -public fun CharSequence.toSet(): Set { - return when (length) { - 0 -> emptySet() - 1 -> setOf(this[0]) - else -> toCollection(LinkedHashSet(mapCapacity(length))) - } -} - -/** - * Returns a [SortedSet] of all characters. - */ -// TODO: Add SortedSet impl -//@kotlin.jvm.JvmVersion -//public fun CharSequence.toSortedSet(): SortedSet { -// return toCollection(TreeSet()) -//} - -/** - * Returns a single list of all elements yielded from results of [transform] function being invoked on each character of original char sequence. - */ -public inline fun CharSequence.flatMap(transform: (Char) -> Iterable): List { - return flatMapTo(ArrayList(), transform) -} - -/** - * Appends all elements yielded from results of [transform] function being invoked on each character of original char sequence, to the given [destination]. - */ -public inline fun > CharSequence.flatMapTo(destination: C, transform: (Char) -> Iterable): C { - for (element in this) { - val list = transform(element) - destination.addAll(list) - } - return destination -} - -/** - * Groups characters of the original char sequence by the key returned by the given [keySelector] function - * applied to each character and returns a map where each group key is associated with a list of corresponding characters. - * - * The returned map preserves the entry iteration order of the keys produced from the original char sequence. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun CharSequence.groupBy(keySelector: (Char) -> K): Map> { - return groupByTo(LinkedHashMap>(), keySelector) -} - -/** - * Groups values returned by the [valueTransform] function applied to each character of the original char sequence - * by the key returned by the given [keySelector] function applied to the character - * and returns a map where each group key is associated with a list of corresponding values. - * - * The returned map preserves the entry iteration order of the keys produced from the original char sequence. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun CharSequence.groupBy(keySelector: (Char) -> K, valueTransform: (Char) -> V): Map> { - return groupByTo(LinkedHashMap>(), keySelector, valueTransform) -} - -/** - * Groups characters of the original char sequence by the key returned by the given [keySelector] function - * applied to each character and puts to the [destination] map each group key associated with a list of corresponding characters. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupBy - */ -public inline fun >> CharSequence.groupByTo(destination: M, keySelector: (Char) -> K): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(element) - } - return destination -} - -/** - * Groups values returned by the [valueTransform] function applied to each character of the original char sequence - * by the key returned by the given [keySelector] function applied to the character - * and puts to the [destination] map each group key associated with a list of corresponding values. - * - * @return The [destination] map. - * - * @sample samples.collections.Collections.Transformations.groupByKeysAndValues - */ -public inline fun >> CharSequence.groupByTo(destination: M, keySelector: (Char) -> K, valueTransform: (Char) -> V): M { - for (element in this) { - val key = keySelector(element) - val list = destination.getOrPut(key) { ArrayList() } - list.add(valueTransform(element)) - } - return destination -} - -/** - * Creates a [Grouping] source from a char sequence to be used later with one of group-and-fold operations - * using the specified [keySelector] function to extract a key from each character. - * - * @sample samples.collections.Collections.Transformations.groupingByEachCount - */ -@SinceKotlin("1.1") -public inline fun CharSequence.groupingBy(crossinline keySelector: (Char) -> K): Grouping { - return object : Grouping { - override fun sourceIterator(): Iterator = this@groupingBy.iterator() - override fun keyOf(element: Char): K = keySelector(element) - } -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each character in the original char sequence. - */ -public inline fun CharSequence.map(transform: (Char) -> R): List { - return mapTo(ArrayList(length), transform) -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to each character and its index in the original char sequence. - * @param [transform] function that takes the index of a character and the character itself - * and returns the result of the transform applied to the character. - */ -public inline fun CharSequence.mapIndexed(transform: (index: Int, Char) -> R): List { - return mapIndexedTo(ArrayList(length), transform) -} - -/** - * Returns a list containing only the non-null results of applying the given [transform] function - * to each character and its index in the original char sequence. - * @param [transform] function that takes the index of a character and the character itself - * and returns the result of the transform applied to the character. - */ -public inline fun CharSequence.mapIndexedNotNull(transform: (index: Int, Char) -> R?): List { - return mapIndexedNotNullTo(ArrayList(), transform) -} - -/** - * Applies the given [transform] function to each character and its index in the original char sequence - * and appends only the non-null results to the given [destination]. - * @param [transform] function that takes the index of a character and the character itself - * and returns the result of the transform applied to the character. - */ -public inline fun > CharSequence.mapIndexedNotNullTo(destination: C, transform: (index: Int, Char) -> R?): C { - forEachIndexed { index, element -> transform(index, element)?.let { destination.add(it) } } - return destination -} - -/** - * Applies the given [transform] function to each character and its index in the original char sequence - * and appends the results to the given [destination]. - * @param [transform] function that takes the index of a character and the character itself - * and returns the result of the transform applied to the character. - */ -public inline fun > CharSequence.mapIndexedTo(destination: C, transform: (index: Int, Char) -> R): C { - var index = 0 - for (item in this) - destination.add(transform(index++, item)) - return destination -} - -/** - * Returns a list containing only the non-null results of applying the given [transform] function - * to each character in the original char sequence. - */ -public inline fun CharSequence.mapNotNull(transform: (Char) -> R?): List { - return mapNotNullTo(ArrayList(), transform) -} - -/** - * Applies the given [transform] function to each character in the original char sequence - * and appends only the non-null results to the given [destination]. - */ -public inline fun > CharSequence.mapNotNullTo(destination: C, transform: (Char) -> R?): C { - forEach { element -> transform(element)?.let { destination.add(it) } } - return destination -} - -/** - * Applies the given [transform] function to each character of the original char sequence - * and appends the results to the given [destination]. - */ -public inline fun > CharSequence.mapTo(destination: C, transform: (Char) -> R): C { - for (item in this) - destination.add(transform(item)) - return destination -} - -/** - * Returns a lazy [Iterable] of [IndexedValue] for each character of the original char sequence. - */ -public fun CharSequence.withIndex(): Iterable> { - return IndexingIterable { iterator() } -} - -/** - * Returns `true` if all characters match the given [predicate]. - */ -public inline fun CharSequence.all(predicate: (Char) -> Boolean): Boolean { - for (element in this) if (!predicate(element)) return false - return true -} - -/** - * Returns `true` if char sequence has at least one character. - */ -public fun CharSequence.any(): Boolean { - for (element in this) return true - return false -} - -/** - * Returns `true` if at least one character matches the given [predicate]. - */ -public inline fun CharSequence.any(predicate: (Char) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return true - return false -} - -/** - * Returns the length of this char sequence. - */ -@kotlin.internal.InlineOnly -public inline fun CharSequence.count(): Int { - return length -} - -/** - * Returns the number of characters matching the given [predicate]. - */ -public inline fun CharSequence.count(predicate: (Char) -> Boolean): Int { - var count = 0 - for (element in this) if (predicate(element)) count++ - return count -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right to current accumulator value and each character. - */ -public inline fun CharSequence.fold(initial: R, operation: (acc: R, Char) -> R): R { - var accumulator = initial - for (element in this) accumulator = operation(accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from left to right - * to current accumulator value and each character with its index in the original char sequence. - * @param [operation] function that takes the index of a character, current accumulator value - * and the character itself, and calculates the next accumulator value. - */ -public inline fun CharSequence.foldIndexed(initial: R, operation: (index: Int, acc: R, Char) -> R): R { - var index = 0 - var accumulator = initial - for (element in this) accumulator = operation(index++, accumulator, element) - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left to each character and current accumulator value. - */ -public inline fun CharSequence.foldRight(initial: R, operation: (Char, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with [initial] value and applying [operation] from right to left - * to each character with its index in the original char sequence and current accumulator value. - * @param [operation] function that takes the index of a character, the character itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun CharSequence.foldRightIndexed(initial: R, operation: (index: Int, Char, acc: R) -> R): R { - var index = lastIndex - var accumulator = initial - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Performs the given [action] on each character. - */ -public inline fun CharSequence.forEach(action: (Char) -> Unit): Unit { - for (element in this) action(element) -} - -/** - * Performs the given [action] on each character, providing sequential index with the character. - * @param [action] function that takes the index of a character and the character itself - * and performs the desired action on the character. - */ -public inline fun CharSequence.forEachIndexed(action: (index: Int, Char) -> Unit): Unit { - var index = 0 - for (item in this) action(index++, item) -} - -/** - * Returns the largest character or `null` if there are no characters. - */ -public fun CharSequence.max(): Char? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (max < e) max = e - } - return max -} - -/** - * Returns the first character yielding the largest value of the given function or `null` if there are no characters. - */ -public inline fun > CharSequence.maxBy(selector: (Char) -> R): Char? { - if (isEmpty()) return null - var maxElem = this[0] - var maxValue = selector(maxElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (maxValue < v) { - maxElem = e - maxValue = v - } - } - return maxElem -} - -/** - * Returns the first character having the largest value according to the provided [comparator] or `null` if there are no characters. - */ -public fun CharSequence.maxWith(comparator: Comparator): Char? { - if (isEmpty()) return null - var max = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(max, e) < 0) max = e - } - return max -} - -/** - * Returns the smallest character or `null` if there are no characters. - */ -public fun CharSequence.min(): Char? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (min > e) min = e - } - return min -} - -/** - * Returns the first character yielding the smallest value of the given function or `null` if there are no characters. - */ -public inline fun > CharSequence.minBy(selector: (Char) -> R): Char? { - if (isEmpty()) return null - var minElem = this[0] - var minValue = selector(minElem) - for (i in 1..lastIndex) { - val e = this[i] - val v = selector(e) - if (minValue > v) { - minElem = e - minValue = v - } - } - return minElem -} - -/** - * Returns the first character having the smallest value according to the provided [comparator] or `null` if there are no characters. - */ -public fun CharSequence.minWith(comparator: Comparator): Char? { - if (isEmpty()) return null - var min = this[0] - for (i in 1..lastIndex) { - val e = this[i] - if (comparator.compare(min, e) > 0) min = e - } - return min -} - -/** - * Returns `true` if the char sequence has no characters. - */ -public fun CharSequence.none(): Boolean { - for (element in this) return false - return true -} - -/** - * Returns `true` if no characters match the given [predicate]. - */ -public inline fun CharSequence.none(predicate: (Char) -> Boolean): Boolean { - for (element in this) if (predicate(element)) return false - return true -} - -/** - * Performs the given [action] on each character and returns the char sequence itself afterwards. - */ -@SinceKotlin("1.1") -public inline fun S.onEach(action: (Char) -> Unit): S { - return apply { for (element in this) action(element) } -} - -/** - * Accumulates value starting with the first character and applying [operation] from left to right to current accumulator value and each character. - */ -public inline fun CharSequence.reduce(operation: (acc: Char, Char) -> Char): Char { - if (isEmpty()) - throw UnsupportedOperationException("Empty char sequence can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with the first character and applying [operation] from left to right - * to current accumulator value and each character with its index in the original char sequence. - * @param [operation] function that takes the index of a character, current accumulator value - * and the character itself and calculates the next accumulator value. - */ -public inline fun CharSequence.reduceIndexed(operation: (index: Int, acc: Char, Char) -> Char): Char { - if (isEmpty()) - throw UnsupportedOperationException("Empty char sequence can't be reduced.") - var accumulator = this[0] - for (index in 1..lastIndex) { - accumulator = operation(index, accumulator, this[index]) - } - return accumulator -} - -/** - * Accumulates value starting with last character and applying [operation] from right to left to each character and current accumulator value. - */ -public inline fun CharSequence.reduceRight(operation: (Char, acc: Char) -> Char): Char { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty char sequence can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(get(index--), accumulator) - } - return accumulator -} - -/** - * Accumulates value starting with last character and applying [operation] from right to left - * to each character with its index in the original char sequence and current accumulator value. - * @param [operation] function that takes the index of a character, the character itself - * and current accumulator value, and calculates the next accumulator value. - */ -public inline fun CharSequence.reduceRightIndexed(operation: (index: Int, Char, acc: Char) -> Char): Char { - var index = lastIndex - if (index < 0) throw UnsupportedOperationException("Empty char sequence can't be reduced.") - var accumulator = get(index--) - while (index >= 0) { - accumulator = operation(index, get(index), accumulator) - --index - } - return accumulator -} - -/** - * Returns the sum of all values produced by [selector] function applied to each character in the char sequence. - */ -public inline fun CharSequence.sumBy(selector: (Char) -> Int): Int { - var sum: Int = 0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Returns the sum of all values produced by [selector] function applied to each character in the char sequence. - */ -public inline fun CharSequence.sumByDouble(selector: (Char) -> Double): Double { - var sum: Double = 0.0 - for (element in this) { - sum += selector(element) - } - return sum -} - -/** - * Splits this char sequence into a list of strings each not exceeding the given [size]. - * - * The last string in the resulting list may have less characters than the given [size]. - * - * @param size the number of elements to take in each string, must be positive and can be greater than the number of elements in this char sequence. - * - * @sample samples.collections.Collections.Transformations.chunked - */ -@SinceKotlin("1.2") -public fun CharSequence.chunked(size: Int): List { - return windowed(size, size, partialWindows = true) -} - -/** - * Splits this char sequence into several char sequences each not exceeding the given [size] - * and applies the given [transform] function to an each. - * - * @return list of results of the [transform] applied to an each char sequence. - * - * Note that the char sequence passed to the [transform] function is ephemeral and is valid only inside that function. - * You should not store it or allow it to escape in some way, unless you made a snapshot of it. - * The last char sequence may have less characters than the given [size]. - * - * @param size the number of elements to take in each char sequence, must be positive and can be greater than the number of elements in this char sequence. - * - * @sample samples.text.Strings.chunkedTransform - */ -@SinceKotlin("1.2") -public fun CharSequence.chunked(size: Int, transform: (CharSequence) -> R): List { - return windowed(size, size, partialWindows = true, transform = transform) -} - -/** - * Splits this char sequence into a sequence of strings each not exceeding the given [size]. - * - * The last string in the resulting sequence may have less characters than the given [size]. - * - * @param size the number of elements to take in each string, must be positive and can be greater than the number of elements in this char sequence. - * - * @sample samples.collections.Collections.Transformations.chunked - */ -@SinceKotlin("1.2") -public fun CharSequence.chunkedSequence(size: Int): Sequence { - return chunkedSequence(size) { it.toString() } -} - -/** - * Splits this char sequence into several char sequences each not exceeding the given [size] - * and applies the given [transform] function to an each. - * - * @return sequence of results of the [transform] applied to an each char sequence. - * - * Note that the char sequence passed to the [transform] function is ephemeral and is valid only inside that function. - * You should not store it or allow it to escape in some way, unless you made a snapshot of it. - * The last char sequence may have less characters than the given [size]. - * - * @param size the number of elements to take in each char sequence, must be positive and can be greater than the number of elements in this char sequence. - * - * @sample samples.text.Strings.chunkedTransformToSequence - */ -@SinceKotlin("1.2") -public fun CharSequence.chunkedSequence(size: Int, transform: (CharSequence) -> R): Sequence { - return windowedSequence(size, size, partialWindows = true, transform = transform) -} - -/** - * Splits the original char sequence into pair of char sequences, - * where *first* char sequence contains characters for which [predicate] yielded `true`, - * while *second* char sequence contains characters for which [predicate] yielded `false`. - */ -public inline fun CharSequence.partition(predicate: (Char) -> Boolean): Pair { - val first = StringBuilder() - val second = StringBuilder() - for (element in this) { - if (predicate(element)) { - first.append(element) - } else { - second.append(element) - } - } - return Pair(first, second) -} - -/** - * Splits the original string into pair of strings, - * where *first* string contains characters for which [predicate] yielded `true`, - * while *second* string contains characters for which [predicate] yielded `false`. - */ -public inline fun String.partition(predicate: (Char) -> Boolean): Pair { - val first = StringBuilder() - val second = StringBuilder() - for (element in this) { - if (predicate(element)) { - first.append(element) - } else { - second.append(element) - } - } - return Pair(first.toString(), second.toString()) -} - -/** - * Returns a list of snapshots of the window of the given [size] - * sliding along this char sequence with the given [step], where each - * snapshot is a string. - * - * Several last strings may have less characters than the given [size]. - * - * Both [size] and [step] must be positive and can be greater than the number of elements in this char sequence. - * @param size the number of elements to take in each window - * @param step the number of elements to move the window forward by on an each step, by default 1 - * @param partialWindows controls whether or not to keep partial windows in the end if any, - * by default `false` which means partial windows won't be preserved - * - * @sample samples.collections.Sequences.Transformations.takeWindows - */ -@SinceKotlin("1.2") -public fun CharSequence.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false): List { - return windowed(size, step, partialWindows) { it.toString() } -} - -/** - * Returns a list of results of applying the given [transform] function to - * an each char sequence representing a view over the window of the given [size] - * sliding along this char sequence with the given [step]. - * - * Note that the char sequence passed to the [transform] function is ephemeral and is valid only inside that function. - * You should not store it or allow it to escape in some way, unless you made a snapshot of it. - * Several last char sequences may have less characters than the given [size]. - * - * Both [size] and [step] must be positive and can be greater than the number of elements in this char sequence. - * @param size the number of elements to take in each window - * @param step the number of elements to move the window forward by on an each step, by default 1 - * @param partialWindows controls whether or not to keep partial windows in the end if any, - * by default `false` which means partial windows won't be preserved - * - * @sample samples.collections.Sequences.Transformations.averageWindows - */ -@SinceKotlin("1.2") -public fun CharSequence.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false, transform: (CharSequence) -> R): List { - checkWindowSizeStep(size, step) - val thisSize = this.length - val result = ArrayList((thisSize + step - 1) / step) - var index = 0 - while (index < thisSize) { - val end = index + size - val coercedEnd = if (end > thisSize) { if (partialWindows) thisSize else break } else end - result.add(transform(subSequence(index, coercedEnd))) - index += step - } - return result -} - -/** - * Returns a sequence of snapshots of the window of the given [size] - * sliding along this char sequence with the given [step], where each - * snapshot is a string. - * - * Several last strings may have less characters than the given [size]. - * - * Both [size] and [step] must be positive and can be greater than the number of elements in this char sequence. - * @param size the number of elements to take in each window - * @param step the number of elements to move the window forward by on an each step, by default 1 - * @param partialWindows controls whether or not to keep partial windows in the end if any, - * by default `false` which means partial windows won't be preserved - * - * @sample samples.collections.Sequences.Transformations.takeWindows - */ -@SinceKotlin("1.2") -public fun CharSequence.windowedSequence(size: Int, step: Int = 1, partialWindows: Boolean = false): Sequence { - return windowedSequence(size, step, partialWindows) { it.toString() } -} - -/** - * Returns a sequence of results of applying the given [transform] function to - * an each char sequence representing a view over the window of the given [size] - * sliding along this char sequence with the given [step]. - * - * Note that the char sequence passed to the [transform] function is ephemeral and is valid only inside that function. - * You should not store it or allow it to escape in some way, unless you made a snapshot of it. - * Several last char sequences may have less characters than the given [size]. - * - * Both [size] and [step] must be positive and can be greater than the number of elements in this char sequence. - * @param size the number of elements to take in each window - * @param step the number of elements to move the window forward by on an each step, by default 1 - * @param partialWindows controls whether or not to keep partial windows in the end if any, - * by default `false` which means partial windows won't be preserved - * - * @sample samples.collections.Sequences.Transformations.averageWindows - */ -@SinceKotlin("1.2") -public fun CharSequence.windowedSequence(size: Int, step: Int = 1, partialWindows: Boolean = false, transform: (CharSequence) -> R): Sequence { - checkWindowSizeStep(size, step) - val windows = (if (partialWindows) indices else 0 until length - size + 1) step step - return windows.asSequence().map { index -> transform(subSequence(index, (index + size).coerceAtMost(length))) } -} - -/** - * Returns a list of pairs built from characters of both char sequences with same indexes. List has length of shortest char sequence. - */ -public infix fun CharSequence.zip(other: CharSequence): List> { - return zip(other) { c1, c2 -> c1 to c2 } -} - -/** - * Returns a list of values built from characters of both char sequences with same indexes using provided [transform]. List has length of shortest char sequence. - */ -public inline fun CharSequence.zip(other: CharSequence, transform: (a: Char, b: Char) -> V): List { - val length = minOf(this.length, other.length) - val list = ArrayList(length) - for (i in 0..length-1) { - list.add(transform(this[i], other[i])) - } - return list -} - -/** - * Returns a list of pairs of each two adjacent characters in this char sequence. - * - * The returned list is empty if this char sequence contains less than two characters. - * - * @sample samples.collections.Collections.Transformations.zipWithNext - */ -@SinceKotlin("1.2") -public fun CharSequence.zipWithNext(): List> { - return zipWithNext { a, b -> a to b } -} - -/** - * Returns a list containing the results of applying the given [transform] function - * to an each pair of two adjacent characters in this char sequence. - * - * The returned list is empty if this char sequence contains less than two characters. - * - * @sample samples.collections.Collections.Transformations.zipWithNextToFindDeltas - */ -@SinceKotlin("1.2") -public inline fun CharSequence.zipWithNext(transform: (a: Char, b: Char) -> R): List { - val size = length - 1 - if (size < 1) return emptyList() - val result = ArrayList(size) - for (index in 0..size - 1) { - result.add(transform(this[index], this[index + 1])) - } - return result -} - -/** - * Creates an [Iterable] instance that wraps the original char sequence returning its characters when being iterated. - */ -public fun CharSequence.asIterable(): Iterable { - if (this is String && isEmpty()) return emptyList() - return Iterable { this.iterator() } -} - -/** - * Creates a [Sequence] instance that wraps the original char sequence returning its characters when being iterated. - */ -public fun CharSequence.asSequence(): Sequence { - if (this is String && isEmpty()) return emptySequence() - return Sequence { this.iterator() } -} - /** * Returns a string containing this char sequence repeated [n] times. * @throws [IllegalArgumentException] when n < 0. * @sample samples.text.Strings.repeat */ -public fun CharSequence.repeat(n: Int): String { +public actual fun CharSequence.repeat(n: Int): String { require (n >= 0) { "Count 'n' must be non-negative, but was $n." } return when (n) { @@ -2578,22 +44,3 @@ public fun CharSequence.repeat(n: Int): String { } } } - - -/** - * Converts the string into a regular expression [Regex] with the default options. - */ -@kotlin.internal.InlineOnly -public inline fun String.toRegex(): Regex = Regex(this) - -/** - * Converts the string into a regular expression [Regex] with the specified single [option]. - */ -@kotlin.internal.InlineOnly -public inline fun String.toRegex(option: RegexOption): Regex = Regex(this, option) - -/** - * Converts the string into a regular expression [Regex] with the specified set of [options]. - */ -@kotlin.internal.InlineOnly -public inline fun String.toRegex(options: Set): Regex = Regex(this, options) diff --git a/runtime/src/main/kotlin/kotlin/text/regex/Lexer.kt b/runtime/src/main/kotlin/kotlin/text/regex/Lexer.kt index babb968898b..b4020caf941 100644 --- a/runtime/src/main/kotlin/kotlin/text/regex/Lexer.kt +++ b/runtime/src/main/kotlin/kotlin/text/regex/Lexer.kt @@ -532,7 +532,7 @@ internal class Lexer(val patternString: String, flags: Int) { try { val minParsed = sb.toString().toInt() min = if (minParsed >= 0) minParsed else throw PatternSyntaxException() - sb.length = 0 + sb.setLength(0) } catch (nfe: NumberFormatException) { throw PatternSyntaxException() } diff --git a/runtime/src/main/kotlin/kotlin/util/Lateinit.kt b/runtime/src/main/kotlin/kotlin/util/Lateinit.kt deleted file mode 100644 index c58baaa7a6c..00000000000 --- a/runtime/src/main/kotlin/kotlin/util/Lateinit.kt +++ /dev/null @@ -1,19 +0,0 @@ -@file:Suppress("unused", "WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE") - -package kotlin - -import kotlin.internal.InlineOnly -import kotlin.internal.AccessibleLateinitPropertyLiteral -import kotlin.reflect.KProperty0 -import konan.internal.Intrinsic - -/** - * Returns `true` if this lateinit property has been assigned a value, and `false` otherwise. - * - * Cannot be used in an inline function, to avoid binary compatibility issues. - */ -@SinceKotlin("1.2") -@InlineOnly -@Intrinsic -inline val @receiver:AccessibleLateinitPropertyLiteral KProperty0<*>.isInitialized: Boolean - get() = throw NotImplementedError("Implementation is intrinsic") diff --git a/runtime/src/main/kotlin/kotlin/util/Preconditions.kt b/runtime/src/main/kotlin/kotlin/util/Preconditions.kt deleted file mode 100644 index d67abeb9579..00000000000 --- a/runtime/src/main/kotlin/kotlin/util/Preconditions.kt +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin - -/** - * Throws an [IllegalArgumentException] if the [value] is false. - * - * @sample samples.misc.Preconditions.failRequireWithLazyMessage - */ -@kotlin.internal.InlineOnly -public inline fun require(value: Boolean): Unit = require(value) { "Failed requirement." } - -/** - * Throws an [IllegalArgumentException] with the result of calling [lazyMessage] if the [value] is false. - * - * @sample samples.misc.Preconditions.failRequireWithLazyMessage - */ -@kotlin.internal.InlineOnly -public inline fun require(value: Boolean, lazyMessage: () -> Any): Unit { - if (!value) { - val message = lazyMessage() - throw IllegalArgumentException(message.toString()) - } -} - -/** - * Throws an [IllegalArgumentException] if the [value] is null. Otherwise returns the not null value. - */ -@kotlin.internal.InlineOnly -public inline fun requireNotNull(value: T?): T = requireNotNull(value) { "Required value was null." } - -/** - * Throws an [IllegalArgumentException] with the result of calling [lazyMessage] if the [value] is null. Otherwise - * returns the not null value. - * - * @sample samples.misc.Preconditions.failRequireWithLazyMessage - */ -@kotlin.internal.InlineOnly -public inline fun requireNotNull(value: T?, lazyMessage: () -> Any): T { - if (value == null) { - val message = lazyMessage() - throw IllegalArgumentException(message.toString()) - } else { - return value - } -} - -/** - * Throws an [IllegalStateException] if the [value] is false. - * - * @sample samples.misc.Preconditions.failCheckWithLazyMessage - */ -@kotlin.internal.InlineOnly -public inline fun check(value: Boolean): Unit = check(value) { "Check failed." } - -/** - * Throws an [IllegalStateException] with the result of calling [lazyMessage] if the [value] is false. - * - * @sample samples.misc.Preconditions.failCheckWithLazyMessage - */ -@kotlin.internal.InlineOnly -public inline fun check(value: Boolean, lazyMessage: () -> Any): Unit { - if (!value) { - val message = lazyMessage() - throw IllegalStateException(message.toString()) - } -} - -/** - * Throws an [IllegalStateException] if the [value] is null. Otherwise - * returns the not null value. - * - * @sample samples.misc.Preconditions.failCheckWithLazyMessage - */ -@kotlin.internal.InlineOnly -public inline fun checkNotNull(value: T?): T = checkNotNull(value) { "Required value was null." } - -/** - * Throws an [IllegalStateException] with the result of calling [lazyMessage] if the [value] is null. Otherwise - * returns the not null value. - * - * @sample samples.misc.Preconditions.failCheckWithLazyMessage - */ -@kotlin.internal.InlineOnly -public inline fun checkNotNull(value: T?, lazyMessage: () -> Any): T { - if (value == null) { - val message = lazyMessage() - throw IllegalStateException(message.toString()) - } else { - return value - } -} - -/** - * Throws an [IllegalStateException] with the given [message]. - * - * @sample samples.misc.Preconditions.failWithError - */ -@kotlin.internal.InlineOnly -public inline fun error(message: Any): Nothing = throw IllegalStateException(message.toString()) diff --git a/runtime/src/main/kotlin/kotlin/util/Standard.kt b/runtime/src/main/kotlin/kotlin/util/Standard.kt deleted file mode 100644 index c7def28d7f3..00000000000 --- a/runtime/src/main/kotlin/kotlin/util/Standard.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin - -/** - * An exception is thrown to indicate that a method body remains to be implemented. - */ -public class NotImplementedError(message: String) : Error(message) - -/** - * Always throws [NotImplementedError] stating that operation is not implemented. - */ - -@kotlin.internal.InlineOnly -public inline fun TODO(): Nothing = throw NotImplementedError("An operation is not implemented.") - -/** - * Always throws [NotImplementedError] stating that operation is not implemented. - * - * @param reason a string explaining why the implementation is missing. - */ -@kotlin.internal.InlineOnly -public inline fun TODO(reason: String): Nothing = throw NotImplementedError("An operation is not implemented: $reason") - - -/** - * Calls the specified function [block] and returns its result. - */ -@kotlin.internal.InlineOnly -public inline fun run(block: () -> R): R = block() - -/** - * Calls the specified function [block] with `this` value as its receiver and returns its result. - */ -@kotlin.internal.InlineOnly -public inline fun T.run(block: T.() -> R): R = block() - -/** - * Calls the specified function [block] with the given [receiver] as its receiver and returns its result. - */ -@kotlin.internal.InlineOnly -public inline fun with(receiver: T, block: T.() -> R): R = receiver.block() - -/** - * Calls the specified function [block] with `this` value as its receiver and returns `this` value. - */ -@kotlin.internal.InlineOnly -public inline fun T.apply(block: T.() -> Unit): T { block(); return this } - -/** - * Calls the specified function [block] with `this` value as its argument and returns `this` value. - */ -@kotlin.internal.InlineOnly -@SinceKotlin("1.1") -public inline fun T.also(block: (T) -> Unit): T { block(this); return this } - -/** - * Calls the specified function [block] with `this` value as its argument and returns its result. - */ -@kotlin.internal.InlineOnly -public inline fun T.let(block: (T) -> R): R = block(this) - -/** - * Executes the given function [action] specified number of [times]. - * - * A zero-based index of current iteration is passed as a parameter to [action]. - */ -@kotlin.internal.InlineOnly -public inline fun repeat(times: Int, action: (Int) -> Unit) { - for (index in 0..times - 1) { - action(index) - } -} \ No newline at end of file diff --git a/runtime/src/main/kotlin/kotlin/util/Tuples.kt b/runtime/src/main/kotlin/kotlin/util/Tuples.kt deleted file mode 100644 index b6176e1f6bd..00000000000 --- a/runtime/src/main/kotlin/kotlin/util/Tuples.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2010-2017 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 kotlin - -/** - * Represents a generic pair of two values. - * - * There is no meaning attached to values in this class, it can be used for any purpose. - * Pair exhibits value semantics, i.e. two pairs are equal if both components are equal. - * - * An example of decomposing it into values: - * @sample samples.misc.Tuples.pairDestructuring - * - * @param A type of the first value. - * @param B type of the second value. - * @property first First value. - * @property second Second value. - * @constructor Creates a new instance of Pair. - */ -public data class Pair( - public val first: A, - public val second: B -) { - - /** - * Returns string representation of the [Pair] including its [first] and [second] values. - */ - public override fun toString(): String = "($first, $second)" -} - -/** - * Creates a tuple of type [Pair] from this and [that]. - * - * This can be useful for creating [Map] literals with less noise, for example: - * @sample samples.collections.Maps.Instantiation.mapFromPairs - */ -public infix fun A.to(that: B): Pair = Pair(this, that) - -/** - * Converts this pair into a list. - */ -public fun Pair.toList(): List = listOf(first, second) - -/** - * Represents a triad of values - * - * There is no meaning attached to values in this class, it can be used for any purpose. - * Triple exhibits value semantics, i.e. two triples are equal if all three components are equal. - * An example of decomposing it into values: - * @sample samples.misc.Tuples.tripleDestructuring - * - * @param A type of the first value. - * @param B type of the second value. - * @param C type of the third value. - * @property first First value. - * @property second Second value. - * @property third Third value. - */ -public data class Triple( - public val first: A, - public val second: B, - public val third: C -) { - - /** - * Returns string representation of the [Triple] including its [first], [second] and [third] values. - */ - public override fun toString(): String = "($first, $second, $third)" -} - -/** - * Converts this triple into a list. - */ -public fun Triple.toList(): List = listOf(first, second, third) diff --git a/samples/csvparser/src/main/kotlin/CsvParser.kt b/samples/csvparser/src/main/kotlin/CsvParser.kt index 00de0a6236c..1d931da2d58 100644 --- a/samples/csvparser/src/main/kotlin/CsvParser.kt +++ b/samples/csvparser/src/main/kotlin/CsvParser.kt @@ -30,7 +30,7 @@ fun parseLine(line: String, separator: Char) : List { (ch == '\n') || (ch == '\r') -> {} (ch == separator) && (quotes % 2 == 0) -> { result.add(builder.toString()) - builder.length = 0 + builder.setLength(0) } else -> builder.append(ch) }