Common stdlib
- adds actual matching expect declarations - removes duplicates - rewrite collections - add MPP and experimental compiler options
This commit is contained in:
committed by
Pavel Punegov
parent
c807fca8cb
commit
374397d03f
@@ -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"
|
||||
|
||||
+14
-2
@@ -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)
|
||||
|
||||
+3
-1
@@ -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!!
|
||||
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -28,4 +28,4 @@ public annotation class Volatile
|
||||
public annotation class Synchronized
|
||||
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <R> synchronized(@Suppress("UNUSED_PARAMETER") lock: Any, crossinline block: () -> R): R = block()
|
||||
public actual inline fun <R> synchronized(@Suppress("UNUSED_PARAMETER") lock: Any, block: () -> R): R = block()
|
||||
@@ -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
|
||||
@@ -27,59 +27,6 @@ internal external fun <T> getContinuation(): Continuation<T>
|
||||
@PublishedApi
|
||||
internal external suspend fun <T> returnIfSuspended(@Suppress("UNUSED_PARAMETER") argument: Any?): T
|
||||
|
||||
// Single-threaded continuation.
|
||||
class SafeContinuation<in T>
|
||||
constructor(
|
||||
private val delegate: Continuation<T>,
|
||||
initialResult: Any?
|
||||
) : Continuation<T> {
|
||||
|
||||
constructor(delegate: Continuation<T>) : 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 <T> interceptContinuationIfNeeded(
|
||||
|
||||
@@ -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
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
|
||||
+11
-9
@@ -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<out T>(public val index: Int, public val value: T)
|
||||
actual interface Comparator<T> {
|
||||
actual fun compare(a: T, b: T): Int
|
||||
}
|
||||
|
||||
actual inline fun <T> Comparator(crossinline comparison: (a: T, b: T) -> Int): Comparator<T> {
|
||||
return object: Comparator<T> {
|
||||
override fun compare(a: T, b: T) = comparison(a, b)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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<KotlinVersion> {
|
||||
/**
|
||||
* 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)
|
||||
}
|
||||
}
|
||||
@@ -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<out T> {
|
||||
/**
|
||||
* 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 <T> lazyOf(value: T): Lazy<T> = 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 <T> lazyOf(value: T): Lazy<T> = InitializedLazyImpl(value)
|
||||
* the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future.
|
||||
*/
|
||||
@FixmeConcurrency
|
||||
public fun <T> lazy(initializer: () -> T): Lazy<T> = UnsafeLazyImpl(initializer)//SynchronizedLazyImpl(initializer)
|
||||
public actual fun <T> lazy(initializer: () -> T): Lazy<T> = UnsafeLazyImpl(initializer)//SynchronizedLazyImpl(initializer)
|
||||
|
||||
/**
|
||||
* Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]
|
||||
@@ -64,7 +41,7 @@ public fun <T> lazy(initializer: () -> T): Lazy<T> = UnsafeLazyImpl(initializer)
|
||||
* Also this behavior can be changed in the future.
|
||||
*/
|
||||
@FixmeConcurrency
|
||||
public fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
|
||||
public actual fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
|
||||
when (mode) {
|
||||
LazyThreadSafetyMode.SYNCHRONIZED -> TODO()//SynchronizedLazyImpl(initializer)
|
||||
LazyThreadSafetyMode.PUBLICATION -> TODO()//SafePublicationLazyImpl(initializer)
|
||||
@@ -84,140 +61,4 @@ public fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
|
||||
*/
|
||||
@FixmeConcurrency
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
public fun <T> lazy(lock: Any?, initializer: () -> T): Lazy<T> = 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 <T> Lazy<T>.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<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, 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<out T>(initializer: () -> T) : Lazy<T>/*, 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<out T>(override val value: T) : Lazy<T>/*, Serializable*/ {
|
||||
|
||||
override fun isInitialized(): Boolean = true
|
||||
|
||||
override fun toString(): String = value.toString()
|
||||
|
||||
}
|
||||
|
||||
//private class SafePublicationLazyImpl<out T>(initializer: () -> T) : Lazy<T>, 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")
|
||||
// }
|
||||
//}
|
||||
public actual fun <T> lazy(lock: Any?, initializer: () -> T): Lazy<T> = TODO()//SynchronizedLazyImpl(initializer, lock)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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<T>: Iterator<T> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-34
@@ -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<out E> protected constructor() : Collection<E> {
|
||||
abstract override val size: Int
|
||||
abstract override fun iterator(): Iterator<E>
|
||||
|
||||
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<Any?>` with the elements of this collection.
|
||||
*/
|
||||
protected open fun toArray(): Array<Any?> = 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 <T> toArray(array: Array<T>): Array<T> = collectionToArray(this, array)
|
||||
}
|
||||
|
||||
public abstract class AbstractMutableCollection<E> protected constructor(): MutableCollection<E>, AbstractCollection<E>() {
|
||||
|
||||
// Bulk Modification Operations
|
||||
+13
-138
@@ -15,131 +15,6 @@
|
||||
*/
|
||||
package kotlin.collections
|
||||
|
||||
public abstract class AbstractList<out E> protected constructor() : AbstractCollection<E>(), List<E> {
|
||||
abstract override val size: Int
|
||||
abstract override fun get(index: Int): E
|
||||
|
||||
override fun iterator(): Iterator<E> = 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<E> = ListIteratorImpl(0)
|
||||
|
||||
override fun listIterator(index: Int): ListIterator<E> = ListIteratorImpl(index)
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int): List<E> = SubList(this, fromIndex, toIndex)
|
||||
|
||||
internal open class SubList<out E>(
|
||||
private val list: AbstractList<E>, private val fromIndex: Int, toIndex: Int) : AbstractList<E>() {
|
||||
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<E> {
|
||||
/** 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<E> {
|
||||
|
||||
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 <Kotlin JVM root>js/js.libraries/src/core/collections/AbstractMutableList.kt).
|
||||
@@ -153,19 +28,19 @@ public abstract class AbstractList<out E> 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<E> protected constructor() : AbstractMutableCollection<E>(), MutableList<E> {
|
||||
public actual abstract class AbstractMutableList<E> protected actual constructor() : AbstractMutableCollection<E>(), MutableList<E> {
|
||||
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<E>): Boolean {
|
||||
override actual fun addAll(index: Int, elements: Collection<E>): Boolean {
|
||||
var i = index
|
||||
var changed = false
|
||||
for (e in elements) {
|
||||
@@ -175,19 +50,19 @@ public abstract class AbstractMutableList<E> protected constructor() : AbstractM
|
||||
return changed
|
||||
}
|
||||
|
||||
override fun clear() {
|
||||
override actual fun clear() {
|
||||
removeRange(0, size)
|
||||
}
|
||||
|
||||
override fun removeAll(elements: Collection<E>): Boolean = removeAll { it in elements }
|
||||
override fun retainAll(elements: Collection<E>): Boolean = removeAll { it !in elements }
|
||||
override actual fun removeAll(elements: Collection<E>): Boolean = removeAll { it in elements }
|
||||
override actual fun retainAll(elements: Collection<E>): Boolean = removeAll { it !in elements }
|
||||
|
||||
|
||||
override fun iterator(): MutableIterator<E> = IteratorImpl()
|
||||
override actual fun iterator(): MutableIterator<E> = 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<E> 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<E> protected constructor() : AbstractM
|
||||
return -1
|
||||
}
|
||||
|
||||
override fun listIterator(): MutableListIterator<E> = listIterator(0)
|
||||
override fun listIterator(index: Int): MutableListIterator<E> = ListIteratorImpl(index)
|
||||
override actual fun listIterator(): MutableListIterator<E> = listIterator(0)
|
||||
override actual fun listIterator(index: Int): MutableListIterator<E> = ListIteratorImpl(index)
|
||||
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int): MutableList<E> = SubList(this, fromIndex, toIndex)
|
||||
override actual fun subList(fromIndex: Int, toIndex: Int): MutableList<E> = SubList(this, fromIndex, toIndex)
|
||||
|
||||
/**
|
||||
* Removes the range of elements from this list starting from [fromIndex] and ending with but not including [toIndex].
|
||||
@@ -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<out E> protected constructor() : AbstractCollection<E>(), Set<E> {
|
||||
|
||||
/**
|
||||
* 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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,40 +16,40 @@
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
class ArrayList<E> private constructor(
|
||||
actual class ArrayList<E> private constructor(
|
||||
private var array: Array<E>,
|
||||
private var offset: Int,
|
||||
private var length: Int,
|
||||
private val backing: ArrayList<E>?
|
||||
) : MutableList<E>, RandomAccess, AbstractMutableCollection<E>() {
|
||||
|
||||
constructor() : this(10)
|
||||
actual constructor() : this(10)
|
||||
|
||||
constructor(initialCapacity: Int) : this(
|
||||
actual constructor(initialCapacity: Int) : this(
|
||||
arrayOfUninitializedElements(initialCapacity), 0, 0, null)
|
||||
|
||||
constructor(c: Collection<E>) : this(c.size) {
|
||||
addAll(c)
|
||||
actual constructor(elements: Collection<E>) : 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<E> private constructor(
|
||||
return false
|
||||
}
|
||||
|
||||
override fun containsAll(elements: Collection<E>): Boolean {
|
||||
override actual fun containsAll(elements: Collection<E>): Boolean {
|
||||
val it = elements.iterator()
|
||||
while (it.hasNext()) {
|
||||
if (!contains(it.next()))return false
|
||||
@@ -66,7 +66,7 @@ class ArrayList<E> 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<E> 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<E> private constructor(
|
||||
return -1
|
||||
}
|
||||
|
||||
override fun iterator(): MutableIterator<E> = Itr(this, 0)
|
||||
override fun listIterator(): MutableListIterator<E> = Itr(this, 0)
|
||||
override actual fun iterator(): MutableIterator<E> = Itr(this, 0)
|
||||
override actual fun listIterator(): MutableListIterator<E> = Itr(this, 0)
|
||||
|
||||
override fun listIterator(index: Int): MutableListIterator<E> {
|
||||
override actual fun listIterator(index: Int): MutableListIterator<E> {
|
||||
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<E>): Boolean {
|
||||
override actual fun addAll(elements: Collection<E>): Boolean {
|
||||
val n = elements.size
|
||||
addAllInternal(offset + length, elements, n)
|
||||
return n > 0
|
||||
}
|
||||
|
||||
override fun addAll(index: Int, elements: Collection<E>): Boolean {
|
||||
override actual fun addAll(index: Int, elements: Collection<E>): 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<E>): Boolean {
|
||||
override actual fun removeAll(elements: Collection<E>): Boolean {
|
||||
return retainOrRemoveAllInternal(offset, length, elements, false) > 0
|
||||
}
|
||||
|
||||
override fun retainAll(elements: Collection<E>): Boolean {
|
||||
override actual fun retainAll(elements: Collection<E>): Boolean {
|
||||
return retainOrRemoveAllInternal(offset, length, elements, true) > 0
|
||||
}
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int): MutableList<E> {
|
||||
override actual fun subList(fromIndex: Int, toIndex: Int): MutableList<E> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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<T, out K> {
|
||||
/** Returns an [Iterator] over the elements of the source of this grouping. */
|
||||
fun sourceIterator(): Iterator<T>
|
||||
/** 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 <T, K, R> Grouping<T, K>.aggregate(
|
||||
operation: (key: K, accumulator: R?, element: T, first: Boolean) -> R
|
||||
): Map<K, R> {
|
||||
return aggregateTo(mutableMapOf<K, R>(), 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 <T, K, R, M : MutableMap<in K, R>> Grouping<T, K>.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 <T, K, R> Grouping<T, K>.fold(
|
||||
initialValueSelector: (key: K, element: T) -> R,
|
||||
operation: (key: K, accumulator: R, element: T) -> R
|
||||
): Map<K, R> =
|
||||
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 <T, K, R, M : MutableMap<in K, R>> Grouping<T, K>.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 <T, K, R> Grouping<T, K>.fold(
|
||||
initialValue: R,
|
||||
operation: (accumulator: R, element: T) -> R
|
||||
): Map<K, R> =
|
||||
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 <T, K, R, M : MutableMap<in K, R>> Grouping<T, K>.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 <S, T : S, K> Grouping<T, K>.reduce(
|
||||
operation: (key: K, accumulator: S, element: T) -> S
|
||||
): Map<K, S> =
|
||||
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 <S, T : S, K, M : MutableMap<in K, S>> Grouping<T, K>.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 <T, K> Grouping<T, K>.eachCount(): Map<K, Int> = eachCountTo(mutableMapOf<K, Int>())
|
||||
|
||||
/**
|
||||
* 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 <T, K, M : MutableMap<in K, Int>> Grouping<T, K>.eachCountTo(destination: M): M =
|
||||
foldTo(destination, 0) { acc, _ -> acc + 1 }
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
class HashMap<K, V> private constructor(
|
||||
actual class HashMap<K, V> private constructor(
|
||||
private var keysArray: Array<K>,
|
||||
private var valuesArray: Array<V>?, // allocated only when actually used, always null in pure HashSet
|
||||
private var presenceArray: IntArray,
|
||||
@@ -26,8 +26,9 @@ class HashMap<K, V> private constructor(
|
||||
) : MutableMap<K, V> {
|
||||
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<K>? = null
|
||||
private var valuesView: HashMapValues<V>? = null
|
||||
@@ -35,36 +36,39 @@ class HashMap<K, V> 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<out K, V>) : this(m.size) {
|
||||
putAll(m)
|
||||
actual constructor(original: Map<out K, V>) : 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<K, V> private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override fun putAll(from: Map<out K, V>) {
|
||||
override actual fun putAll(from: Map<out K, V>) {
|
||||
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<K, V> 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<K, V> private constructor(
|
||||
}
|
||||
keysArray.resetRange(0, length)
|
||||
valuesArray?.resetRange(0, length)
|
||||
size = 0
|
||||
_size = 0
|
||||
length = 0
|
||||
}
|
||||
|
||||
override val keys: MutableSet<K> get() {
|
||||
override actual val keys: MutableSet<K> get() {
|
||||
val cur = keysView
|
||||
return if (cur == null) {
|
||||
val new = HashSet(this)
|
||||
@@ -114,7 +118,7 @@ class HashMap<K, V> private constructor(
|
||||
} else cur
|
||||
}
|
||||
|
||||
override val values: MutableCollection<V> get() {
|
||||
override actual val values: MutableCollection<V> get() {
|
||||
val cur = valuesView
|
||||
return if (cur == null) {
|
||||
val new = HashMapValues(this)
|
||||
@@ -123,7 +127,7 @@ class HashMap<K, V> private constructor(
|
||||
} else cur
|
||||
}
|
||||
|
||||
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> get() {
|
||||
override actual val entries: MutableSet<MutableMap.MutableEntry<K, V>> get() {
|
||||
val cur = entriesView
|
||||
return if (cur == null) {
|
||||
val new = HashMapEntrySet(this)
|
||||
@@ -148,7 +152,7 @@ class HashMap<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> private constructor(
|
||||
keysArray.resetAt(index)
|
||||
removeHashAt(presenceArray[index])
|
||||
presenceArray[index] = TOMBSTONE
|
||||
size--
|
||||
_size--
|
||||
}
|
||||
|
||||
private fun removeHashAt(removedHash: Int) {
|
||||
@@ -386,7 +390,7 @@ class HashMap<K, V> 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<Map.Entry<*, *>>): Boolean {
|
||||
val it = m.iterator()
|
||||
@@ -702,4 +706,4 @@ internal class HashMapEntrySet<K, V> internal constructor(
|
||||
}
|
||||
|
||||
// This hash map keeps insertion order.
|
||||
typealias LinkedHashMap<K, V> = HashMap<K, V>
|
||||
actual typealias LinkedHashMap<K, V> = HashMap<K, V>
|
||||
@@ -16,28 +16,31 @@
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
class HashSet<K> internal constructor(
|
||||
val backing: HashMap<K, *>
|
||||
) : MutableSet<K>, AbstractMutableCollection<K>(), konan.internal.KonanSet<K> {
|
||||
actual class HashSet<E> internal constructor(
|
||||
val backing: HashMap<E, *>
|
||||
) : MutableSet<E>, AbstractMutableCollection<E>(), konan.internal.KonanSet<E> {
|
||||
|
||||
constructor() : this(HashMap<K, Nothing>())
|
||||
actual constructor() : this(HashMap<E, Nothing>())
|
||||
|
||||
constructor(capacity: Int) : this(HashMap<K, Nothing>(capacity))
|
||||
actual constructor(initialCapacity: Int) : this(HashMap<E, Nothing>(initialCapacity))
|
||||
|
||||
constructor(c: Collection<K>) : this(c.size) {
|
||||
addAll(c)
|
||||
actual constructor(elements: Collection<E>) : 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<K> = backing.keysIterator()
|
||||
// This implementation doesn't use a loadFactor
|
||||
actual constructor(initialCapacity: Int, loadFactor: Float) : this(initialCapacity)
|
||||
|
||||
override fun containsAll(elements: Collection<K>): 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<E> = backing.keysIterator()
|
||||
|
||||
override actual fun containsAll(elements: Collection<E>): Boolean {
|
||||
val it = elements.iterator()
|
||||
while (it.hasNext()) {
|
||||
if (!contains(it.next()))
|
||||
@@ -46,7 +49,7 @@ class HashSet<K> internal constructor(
|
||||
return true
|
||||
}
|
||||
|
||||
override fun addAll(elements: Collection<K>): Boolean {
|
||||
override actual fun addAll(elements: Collection<E>): Boolean {
|
||||
val it = elements.iterator()
|
||||
var updated = false
|
||||
while (it.hasNext()) {
|
||||
@@ -60,7 +63,7 @@ class HashSet<K> internal constructor(
|
||||
return other === this ||
|
||||
(other is Set<*>) &&
|
||||
contentEquals(
|
||||
@Suppress("UNCHECKED_CAST") (other as Set<K>))
|
||||
@Suppress("UNCHECKED_CAST") (other as Set<E>))
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
@@ -76,8 +79,8 @@ class HashSet<K> internal constructor(
|
||||
|
||||
// ---------------------------- private ----------------------------
|
||||
|
||||
private fun contentEquals(other: Set<K>): Boolean = size == other.size && containsAll(other)
|
||||
private fun contentEquals(other: Set<E>): Boolean = size == other.size && containsAll(other)
|
||||
}
|
||||
|
||||
// This hash set keeps insertion order.
|
||||
typealias LinkedHashSet<V> = HashSet<V>
|
||||
actual typealias LinkedHashSet<V> = HashSet<V>
|
||||
@@ -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 <T> Iterable(crossinline iterator: () -> Iterator<T>): Iterable<T> = object : Iterable<T> {
|
||||
override fun iterator(): Iterator<T> = iterator()
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper over another [Iterable] (or any other object that can produce an [Iterator]) that returns
|
||||
* an indexing iterator.
|
||||
*/
|
||||
internal class IndexingIterable<out T>(private val iteratorFactory: () -> Iterator<T>) : Iterable<IndexedValue<T>> {
|
||||
override fun iterator(): Iterator<IndexedValue<T>> = IndexingIterator(iteratorFactory())
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the size of this iterable if it is known, or `null` otherwise.
|
||||
*/
|
||||
@PublishedApi
|
||||
internal fun <T> Iterable<T>.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 <T> Iterable<T>.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 <T> Collection<T>.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 <T> Iterable<T>.convertToSetForSetOperationWith(source: Iterable<T>): Collection<T> =
|
||||
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 <T> Iterable<T>.convertToSetForSetOperation(): Collection<T> =
|
||||
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 <T> Iterable<Iterable<T>>.flatten(): List<T> {
|
||||
val result = ArrayList<T>()
|
||||
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 <T, R> Iterable<Pair<T, R>>.unzip(): Pair<List<T>, List<R>> {
|
||||
val expectedSize = collectionSizeOrDefault(10)
|
||||
val listT = ArrayList<T>(expectedSize)
|
||||
val listR = ArrayList<R>(expectedSize)
|
||||
for (pair in this) {
|
||||
listT.add(pair.first)
|
||||
listR.add(pair.second)
|
||||
}
|
||||
return listT to listR
|
||||
}
|
||||
@@ -79,31 +79,3 @@ public abstract class BooleanIterator : Iterator<Boolean> {
|
||||
/** 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 <T> Iterator<T>.iterator(): Iterator<T> = this
|
||||
|
||||
/**
|
||||
* Returns an [Iterator] wrapping each value produced by this [Iterator] with the [IndexedValue],
|
||||
* containing value and it's index.
|
||||
*/
|
||||
public fun <T> Iterator<T>.withIndex(): Iterator<IndexedValue<T>> = IndexingIterator(this)
|
||||
|
||||
/**
|
||||
* Performs the given [operation] on each element of this [Iterator].
|
||||
*/
|
||||
public inline fun <T> Iterator<T>.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<out T>(private val iterator: Iterator<T>) : Iterator<IndexedValue<T>> {
|
||||
private var index = 0
|
||||
final override fun hasNext(): Boolean = iterator.hasNext()
|
||||
final override fun next(): IndexedValue<T> = IndexedValue(index++, iterator.next())
|
||||
}
|
||||
@@ -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 <V, V1: V> Map<in String, @Exact V>.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 <V> MutableMap<in String, in V>.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 <V> MutableMap<in String, in V>.setValue(thisRef: Any?, property: KProperty<*>, value: V) {
|
||||
this.put(property.name, value)
|
||||
}
|
||||
@@ -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 <K, V> Map<K, V>.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 <K, V> Map<K, V>.withDefault(defaultValue: (key: K) -> V): Map<K, V> =
|
||||
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 <K, V> MutableMap<K, V>.withDefault(defaultValue: (key: K) -> V): MutableMap<K, V> =
|
||||
when (this) {
|
||||
is MutableMapWithDefault -> this.map.withDefault(defaultValue)
|
||||
else -> MutableMapWithDefaultImpl(this, defaultValue)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private interface MapWithDefault<K, out V>: Map<K, V> {
|
||||
public val map: Map<K, V>
|
||||
public fun getOrImplicitDefault(key: K): V
|
||||
}
|
||||
|
||||
private interface MutableMapWithDefault<K, V>: MutableMap<K, V>, MapWithDefault<K, V> {
|
||||
public override val map: MutableMap<K, V>
|
||||
}
|
||||
|
||||
|
||||
private class MapWithDefaultImpl<K, out V>(public override val map: Map<K,V>, private val default: (key: K) -> V) : MapWithDefault<K, V> {
|
||||
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<K> get() = map.keys
|
||||
override val values: Collection<V> get() = map.values
|
||||
override val entries: Set<Map.Entry<K, V>> get() = map.entries
|
||||
|
||||
override fun getOrImplicitDefault(key: K): V = map.getOrElseNullable(key, { default(key) })
|
||||
}
|
||||
|
||||
private class MutableMapWithDefaultImpl<K, V>(public override val map: MutableMap<K, V>, private val default: (key: K) -> V): MutableMapWithDefault<K, V> {
|
||||
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<K> get() = map.keys
|
||||
override val values: MutableCollection<V> get() = map.values
|
||||
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> 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<out K, V>) = map.putAll(from)
|
||||
override fun clear() = map.clear()
|
||||
|
||||
override fun getOrImplicitDefault(key: K): V = map.getOrElseNullable(key, { default(key) })
|
||||
}
|
||||
|
||||
@@ -16,863 +16,9 @@
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
private object EmptyMap : Map<Any?, Nothing> {
|
||||
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<Map.Entry<Any?, Nothing>> get() = EmptySet
|
||||
override val keys: Set<Any?> get() = EmptySet
|
||||
override val values: Collection<Nothing> 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 <K, V> emptyMap(): Map<K, V> = EmptyMap as Map<K, V>
|
||||
|
||||
/**
|
||||
* 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 <K, V> mapOf(vararg pairs: Pair<K, V>): Map<K, V> =
|
||||
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 <K, V> mapOf(): Map<K, V> = 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 <K, V> mapOf(pair: Pair<K, V>): Map<K, V> = 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 <K, V> mutableMapOf(vararg pairs: Pair<K, V>): MutableMap<K, V>
|
||||
= HashMap<K, V>(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 <K, V> hashMapOf(vararg pairs: Pair<K, V>): HashMap<K, V>
|
||||
= HashMap<K, V>(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 <K, V> linkedMapOf(vararg pairs: Pair<K, V>): LinkedHashMap<K, V>
|
||||
= LinkedHashMap<K, V>(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 <K, V> Map<out K, V>.isNotEmpty(): Boolean = !isEmpty()
|
||||
|
||||
/**
|
||||
* Returns the [Map] if its not `null`, or the empty [Map] otherwise.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <K, V> Map<K, V>?.orEmpty() : Map<K, V> = 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<out K, V>.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 <K, V> MutableMap<K, V>.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<out K, V>.get(key: K): V?
|
||||
= @Suppress("UNCHECKED_CAST") (this as Map<K, V>).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<out K, *>.containsKey(key: K): Boolean
|
||||
= @Suppress("UNCHECKED_CAST") (this as Map<K, *>).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 <K, @kotlin.internal.OnlyInputTypes V> Map<K, V>.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<out K, V>.remove(key: K): V?
|
||||
= @Suppress("UNCHECKED_CAST") (this as MutableMap<K, V>).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 <K, V> Map.Entry<K, V>.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 <K, V> Map.Entry<K, V>.component2(): V = value
|
||||
|
||||
/**
|
||||
* Converts entry to [Pair] with key being first component and value being second.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <K, V> Map.Entry<K, V>.toPair(): Pair<K, V> = 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 <K, V> Map<K, V>.getOrElse(key: K, defaultValue: () -> V): V = get(key) ?: defaultValue()
|
||||
|
||||
|
||||
internal inline fun <K, V> Map<K, V>.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 <K, V> Map<K, V>.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 <K, V> MutableMap<K, V>.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 <K, V> Map<out K, V>.iterator(): Iterator<Map.Entry<K, V>> = entries.iterator()
|
||||
|
||||
/**
|
||||
* Returns a [MutableIterator] over the mutable entries in the [MutableMap].
|
||||
*
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun <K, V> MutableMap<K, V>.iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> = 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 <K, V, R, M : MutableMap<in K, in R>> Map<out K, V>.mapValuesTo(destination: M, transform: (Map.Entry<K, V>) -> 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 <K, V, R, M : MutableMap<in R, in V>> Map<out K, V>.mapKeysTo(destination: M, transform: (Map.Entry<K, V>) -> 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 <K, V> MutableMap<in K, in V>.putAll(pairs: Array<out Pair<K, V>>): 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 <K, V> MutableMap<in K, in V>.putAll(pairs: Iterable<Pair<K,V>>): 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 <K, V> MutableMap<in K, in V>.putAll(pairs: Sequence<Pair<K,V>>): 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 <K, V, R> Map<out K, V>.mapValues(transform: (Map.Entry<K, V>) -> R): Map<K, R> {
|
||||
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||
return mapValuesTo(HashMap<K, R>(
|
||||
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 <K, V, R> Map<out K, V>.mapKeys(transform: (Map.Entry<K, V>) -> R): Map<R, V> {
|
||||
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
|
||||
return mapKeysTo(HashMap<R, V>(
|
||||
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 <K, V> Map<out K, V>.filterKeys(predicate: (K) -> Boolean): Map<K, V> {
|
||||
val result = HashMap<K, V>()
|
||||
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 <K, V> Map<out K, V>.filterValues(predicate: (V) -> Boolean): Map<K, V> {
|
||||
val result = HashMap<K, V>()
|
||||
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 <K, V, M : MutableMap<in K, in V>> Map<out K, V>.filterTo(destination: M, predicate: (Map.Entry<K, V>) -> 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 <K, V> Map<out K, V>.filter(predicate: (Map.Entry<K, V>) -> Boolean): Map<K, V> {
|
||||
return filterTo(HashMap<K, V>(), predicate)
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends all entries not matching the given [predicate] into the given [destination].
|
||||
*
|
||||
* @return the destination map.
|
||||
*/
|
||||
public inline fun <K, V, M : MutableMap<in K, in V>> Map<out K, V>.filterNotTo(destination: M, predicate: (Map.Entry<K, V>) -> 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 <K, V> Map<out K, V>.filterNot(predicate: (Map.Entry<K, V>) -> Boolean): Map<K, V> {
|
||||
return filterNotTo(HashMap<K, V>(), 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 <K, V> Iterable<Pair<K, V>>.toMap(): Map<K, V> {
|
||||
if (this is Collection) {
|
||||
return when (size) {
|
||||
0 -> emptyMap()
|
||||
1 -> mapOf(if (this is List) this[0] else iterator().next())
|
||||
else -> toMap(HashMap<K, V>(mapCapacity(size)))
|
||||
}
|
||||
}
|
||||
return toMap(HashMap<K, V>()).optimizeReadOnlyMap()
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates and returns the [destination] mutable map with key-value pairs from the given collection of pairs.
|
||||
*/
|
||||
public fun <K, V, M : MutableMap<in K, in V>> Iterable<Pair<K, V>>.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 <K, V> Array<out Pair<K, V>>.toMap(): Map<K, V> = when(size) {
|
||||
0 -> emptyMap()
|
||||
1 -> mapOf(this[0])
|
||||
else -> toMap(HashMap<K, V>(mapCapacity(size)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates and returns the [destination] mutable map with key-value pairs from the given array of pairs.
|
||||
*/
|
||||
public fun <K, V, M : MutableMap<in K, in V>> Array<out Pair<K, V>>.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 <K, V> Sequence<Pair<K, V>>.toMap(): Map<K, V> = toMap(HashMap<K, V>()).optimizeReadOnlyMap()
|
||||
|
||||
/**
|
||||
* Populates and returns the [destination] mutable map with key-value pairs from the given sequence of pairs.
|
||||
*/
|
||||
public fun <K, V, M : MutableMap<in K, in V>> Sequence<Pair<K, V>>.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 <K, V> Map<out K, V>.toMap(): Map<K, V> = 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 <K, V> Map<out K, V>.toMutableMap(): MutableMap<K, V> = HashMap<K, V>(this)
|
||||
|
||||
/**
|
||||
* Populates and returns the [destination] mutable map with key-value pairs from the given map.
|
||||
*/
|
||||
public fun <K, V, M : MutableMap<in K, in V>> Map<out K, V>.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 <K, V> Map<out K, V>.plus(pair: Pair<K, V>): Map<K, V>
|
||||
= if (this.isEmpty()) mapOf(pair) else HashMap<K, V>(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 <K, V> Map<out K, V>.plus(pairs: Iterable<Pair<K, V>>): Map<K, V>
|
||||
= 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 <K, V> Map<out K, V>.plus(pairs: Array<out Pair<K, V>>): Map<K, V>
|
||||
= 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 <K, V> Map<out K, V>.plus(pairs: Sequence<Pair<K, V>>): Map<K, V>
|
||||
= 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 <K, V> Map<out K, V>.plus(map: Map<out K, V>): Map<K, V>
|
||||
= HashMap(this).apply { putAll(map) }
|
||||
|
||||
/**
|
||||
* Appends or replaces the given [pair] in this mutable map.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(pair: Pair<K, V>) {
|
||||
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 <K, V> MutableMap<in K, in V>.plusAssign(pairs: Iterable<Pair<K, V>>) {
|
||||
putAll(pairs)
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends or replaces all pairs from the given array of [pairs] in this mutable map.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(pairs: Array<out Pair<K, V>>) {
|
||||
putAll(pairs)
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends or replaces all pairs from the given sequence of [pairs] in this mutable map.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(pairs: Sequence<Pair<K, V>>) {
|
||||
putAll(pairs)
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends or replaces all entries from the given [map] in this mutable map.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun <K, V> MutableMap<in K, in V>.plusAssign(map: Map<K, V>) {
|
||||
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 <K, V> Map<out K, V>.minus(key: K): Map<K, V>
|
||||
= 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 <K, V> Map<out K, V>.minus(keys: Iterable<K>): Map<K, V>
|
||||
= 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 <K, V> Map<out K, V>.minus(keys: Array<out K>): Map<K, V>
|
||||
= 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 <K, V> Map<out K, V>.minus(keys: Sequence<K>): Map<K, V>
|
||||
= 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 <K, V> MutableMap<K, V>.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 <K, V> MutableMap<K, V>.minusAssign(keys: Iterable<K>) {
|
||||
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 <K, V> MutableMap<K, V>.minusAssign(keys: Array<out K>) {
|
||||
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 <K, V> MutableMap<K, V>.minusAssign(keys: Sequence<K>) {
|
||||
this.keys.removeAll(keys)
|
||||
}
|
||||
|
||||
@kotlin.internal.InlineExposed
|
||||
internal fun <K, V> Map<K, V>.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 <K, V> Map<K, V>.toSingletonMapOrSelf(): Map<K, V> = toSingletonMap()
|
||||
internal inline actual fun <K, V> Map<K, V>.toSingletonMapOrSelf(): Map<K, V> = toSingletonMap()
|
||||
|
||||
// creates a singleton copy of map
|
||||
//internal fun <K, V> Map<out K, V>.toSingletonMap(): Map<K, V>
|
||||
// = 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 <K, V> Map<out K, V>.toList(): List<Pair<K, V>> {
|
||||
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<Pair<K, V>>(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 <K, V, R> Map<out K, V>.flatMap(transform: (Map.Entry<K, V>) -> Iterable<R>): List<R> {
|
||||
return flatMapTo(ArrayList<R>(), 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 <K, V, R, C : MutableCollection<in R>> Map<out K, V>.flatMapTo(destination: C, transform: (Map.Entry<K, V>) -> Iterable<R>): 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 <K, V, R> Map<out K, V>.map(transform: (Map.Entry<K, V>) -> R): List<R> {
|
||||
return mapTo(ArrayList<R>(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 <K, V, R : Any> Map<out K, V>.mapNotNull(transform: (Map.Entry<K, V>) -> R?): List<R> {
|
||||
return mapNotNullTo(ArrayList<R>(), 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 <K, V, R : Any, C : MutableCollection<in R>> Map<out K, V>.mapNotNullTo(destination: C, transform: (Map.Entry<K, V>) -> 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 <K, V, R, C : MutableCollection<in R>> Map<out K, V>.mapTo(destination: C, transform: (Map.Entry<K, V>) -> R): C {
|
||||
for (item in this)
|
||||
destination.add(transform(item))
|
||||
return destination
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if all entries match the given [predicate].
|
||||
*/
|
||||
public inline fun <K, V> Map<out K, V>.all(predicate: (Map.Entry<K, V>) -> Boolean): Boolean {
|
||||
for (element in this) if (!predicate(element)) return false
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if map has at least one entry.
|
||||
*/
|
||||
public fun <K, V> Map<out K, V>.any(): Boolean {
|
||||
for (element in this) return true
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if at least one entry matches the given [predicate].
|
||||
*/
|
||||
public inline fun <K, V> Map<out K, V>.any(predicate: (Map.Entry<K, V>) -> 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 <K, V> Map<out K, V>.count(): Int {
|
||||
return size
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of entries matching the given [predicate].
|
||||
*/
|
||||
public inline fun <K, V> Map<out K, V>.count(predicate: (Map.Entry<K, V>) -> 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 <K, V> Map<out K, V>.forEach(action: (Map.Entry<K, V>) -> 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 <K, V, R : Comparable<R>> Map<out K, V>.maxBy(selector: (Map.Entry<K, V>) -> R): Map.Entry<K, V>? {
|
||||
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 <K, V> Map<out K, V>.maxWith(comparator: Comparator<in Map.Entry<K, V>>): Map.Entry<K, V>? {
|
||||
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 <K, V, R : Comparable<R>> Map<out K, V>.minBy(selector: (Map.Entry<K, V>) -> R): Map.Entry<K, V>? {
|
||||
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 <K, V> Map<out K, V>.minWith(comparator: Comparator<in Map.Entry<K, V>>): Map.Entry<K, V>? {
|
||||
return entries.minWith(comparator)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the map has no entries.
|
||||
*/
|
||||
public fun <K, V> Map<out K, V>.none(): Boolean {
|
||||
for (element in this) return false
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if no entries match the given [predicate].
|
||||
*/
|
||||
public inline fun <K, V> Map<out K, V>.none(predicate: (Map.Entry<K, V>) -> 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 <K, V, M : Map<out K, V>> M.onEach(action: (Map.Entry<K, V>) -> 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 <K, V> Map<out K, V>.asIterable(): Iterable<Map.Entry<K, V>> {
|
||||
return entries
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a [Sequence] instance that wraps the original map returning its entries when being iterated.
|
||||
*/
|
||||
public fun <K, V> Map<out K, V>.asSequence(): Sequence<Map.Entry<K, V>> {
|
||||
return entries.asSequence()
|
||||
}
|
||||
|
||||
internal actual fun <K, V> Map<out K, V>.toSingletonMap(): Map<K, V>
|
||||
= this.toMutableMap() // TODO
|
||||
|
||||
@@ -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<out T>.remove(element: T): Boolean
|
||||
= @Suppress("UNCHECKED_CAST") (this as MutableCollection<T>).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<E>`.
|
||||
*
|
||||
* @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<out T>.removeAll(elements: Collection<T>): Boolean
|
||||
= @Suppress("UNCHECKED_CAST") (this as MutableCollection<T>).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<E>`.
|
||||
*
|
||||
* @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<out T>.retainAll(elements: Collection<T>): Boolean
|
||||
= @Suppress("UNCHECKED_CAST") (this as MutableCollection<T>).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 <T> MutableList<T>.remove(index: Int): T = removeAt(index)
|
||||
|
||||
/**
|
||||
* Adds the specified [element] to this mutable collection.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun <T> MutableCollection<in T>.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 <T> MutableCollection<in T>.plusAssign(elements: Iterable<T>) {
|
||||
this.addAll(elements)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all elements of the given [elements] array to this mutable collection.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun <T> MutableCollection<in T>.plusAssign(elements: Array<T>) {
|
||||
this.addAll(elements)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all elements of the given [elements] sequence to this mutable collection.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun <T> MutableCollection<in T>.plusAssign(elements: Sequence<T>) {
|
||||
this.addAll(elements)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a single instance of the specified [element] from this mutable collection.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun <T> MutableCollection<in T>.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 <T> MutableCollection<in T>.minusAssign(elements: Iterable<T>) {
|
||||
this.removeAll(elements)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all elements contained in the given [elements] array from this mutable collection.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun <T> MutableCollection<in T>.minusAssign(elements: Array<T>) {
|
||||
this.removeAll(elements)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all elements contained in the given [elements] sequence from this mutable collection.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun <T> MutableCollection<in T>.minusAssign(elements: Sequence<T>) {
|
||||
this.removeAll(elements)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all elements of the given [elements] collection to this [MutableCollection].
|
||||
*/
|
||||
public fun <T> MutableCollection<in T>.addAll(elements: Iterable<T>): 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 <T> MutableCollection<in T>.addAll(elements: Sequence<T>): 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 <T> MutableCollection<in T>.addAll(elements: Array<out T>): Boolean {
|
||||
return addAll(elements.asList())
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all elements from this [MutableIterable] that match the given [predicate].
|
||||
*/
|
||||
public fun <T> MutableIterable<T>.removeAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, true)
|
||||
|
||||
/**
|
||||
* Retains only elements of this [MutableIterable] that match the given [predicate].
|
||||
*/
|
||||
public fun <T> MutableIterable<T>.retainAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, false)
|
||||
|
||||
private fun <T> MutableIterable<T>.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 <T> MutableList<T>.removeAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, true)
|
||||
|
||||
/**
|
||||
* Retains only elements of this [MutableList] that match the given [predicate].
|
||||
*/
|
||||
public fun <T> MutableList<T>.retainAll(predicate: (T) -> Boolean): Boolean = filterInPlace(predicate, false)
|
||||
|
||||
private fun <T> MutableList<T>.filterInPlace(predicate: (T) -> Boolean, predicateResultToRemove: Boolean): Boolean {
|
||||
if (this !is RandomAccess)
|
||||
return (this as MutableIterable<T>).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 <T> MutableCollection<in T>.removeAll(elements: Iterable<T>): Boolean {
|
||||
return removeAll(elements.convertToSetForSetOperationWith(this))
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all elements from this [MutableCollection] that are also contained in the given [elements] sequence.
|
||||
*/
|
||||
public fun <T> MutableCollection<in T>.removeAll(elements: Sequence<T>): 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 <T> MutableCollection<in T>.removeAll(elements: Array<out T>): Boolean {
|
||||
return elements.isNotEmpty() && removeAll(elements.toHashSet())
|
||||
}
|
||||
|
||||
/**
|
||||
* Retains only elements of this [MutableCollection] that are contained in the given [elements] collection.
|
||||
*/
|
||||
public fun <T> MutableCollection<in T>.retainAll(elements: Iterable<T>): Boolean {
|
||||
return retainAll(elements.convertToSetForSetOperationWith(this))
|
||||
}
|
||||
|
||||
/**
|
||||
* Retains only elements of this [MutableCollection] that are contained in the given [elements] array.
|
||||
*/
|
||||
public fun <T> MutableCollection<in T>.retainAll(elements: Array<out T>): 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 <T> MutableCollection<in T>.retainAll(elements: Sequence<T>): 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 <T : Comparable<T>> MutableList<T>.sort(): Unit = sortWith(Comparator<T> { a: T, b: T -> a.compareTo(b) })
|
||||
public actual fun <T : Comparable<T>> MutableList<T>.sort(): Unit = sortWith(Comparator<T> { a: T, b: T -> a.compareTo(b) })
|
||||
|
||||
/**
|
||||
* Sorts elements in the list in-place according to the order specified with [comparator].
|
||||
*/
|
||||
public fun <T> MutableList<T>.sortWith(comparator: Comparator<in T>): Unit {
|
||||
public actual fun <T> MutableList<T>.sortWith(comparator: Comparator<in T>): Unit {
|
||||
if (size > 1) {
|
||||
val it = listIterator()
|
||||
val sortedArray = @Suppress("TYPE_PARAMETER_AS_REIFIED") toTypedArray().apply { sortWith(comparator) }
|
||||
@@ -289,3 +36,51 @@ public fun <T> MutableList<T>.sortWith(comparator: Comparator<in T>): 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<K, V> protected actual constructor() : AbstractMap<K, V>(), MutableMap<K, V> {
|
||||
/**
|
||||
* 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<K>
|
||||
|
||||
/**
|
||||
* Returns a [Collection] of all values in this map.
|
||||
*/
|
||||
abstract override val values: MutableCollection<V>
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<E> protected actual constructor() : AbstractSet<E>(), MutableSet<E> {
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
@@ -16,4 +16,5 @@
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
public interface RandomAccess
|
||||
// A marker interface indicating the fast indexed access support
|
||||
public actual interface RandomAccess
|
||||
|
||||
@@ -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<out T>(private val delegate: List<T>) : AbstractList<T>() {
|
||||
override val size: Int get() = delegate.size
|
||||
override fun get(index: Int): T = delegate[reverseElementIndex(index)]
|
||||
|
||||
}
|
||||
|
||||
private class ReversedList<T>(private val delegate: MutableList<T>) : AbstractMutableList<T>() {
|
||||
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 <T> List<T>.asReversed(): List<T> = 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 <T> MutableList<T>.asReversed(): MutableList<T> = ReversedList(this)
|
||||
@@ -52,3 +52,9 @@ public interface MutableSet<E> : Set<E>, MutableCollection<E> {
|
||||
override fun retainAll(elements: Collection<E>): Boolean
|
||||
override fun clear(): Unit
|
||||
}
|
||||
|
||||
// TODO: Add SingletonSet class
|
||||
/**
|
||||
* Returns an immutable set containing only the specified object [element].
|
||||
*/
|
||||
public fun <T> setOf(element: T): Set<T> = hashSetOf(element)
|
||||
|
||||
@@ -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<Nothing>, konan.internal.KonanSet<Nothing> {
|
||||
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<Nothing>): Boolean = elements.isEmpty()
|
||||
|
||||
override fun iterator(): Iterator<Nothing> = EmptyIterator
|
||||
|
||||
private fun readResolve(): Any = EmptySet
|
||||
}
|
||||
|
||||
|
||||
/** Returns an empty read-only set. The returned set is serializable (JVM). */
|
||||
public fun <T> emptySet(): Set<T> = 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 <T> setOf(vararg elements: T): Set<T> = if (elements.size > 0) elements.toSet() else emptySet()
|
||||
|
||||
/** Returns an empty read-only set. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <T> setOf(): Set<T> = emptySet()
|
||||
|
||||
/**
|
||||
* Returns a new [MutableSet] with the given elements.
|
||||
* Elements of the set are iterated in the order they were specified.
|
||||
*/
|
||||
public fun <T> mutableSetOf(vararg elements: T): MutableSet<T> = elements.toCollection(HashSet<T>(mapCapacity(elements.size)))
|
||||
|
||||
/** Returns a new [HashSet] with the given elements. */
|
||||
public fun <T> hashSetOf(vararg elements: T): HashSet<T> = elements.toCollection(HashSet<T>(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 <T> linkedSetOf(vararg elements: T): LinkedHashSet<T> = 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 <T> Set<T>?.orEmpty(): Set<T> = this ?: emptySet()
|
||||
|
||||
// TODO: Add SingletonSet class
|
||||
/**
|
||||
* Returns an immutable set containing only the specified object [element].
|
||||
*/
|
||||
public fun <T> setOf(element: T): Set<T> = hashSetOf(element)
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new [SortedSet] with the given elements.
|
||||
*/
|
||||
// public fun <T> sortedSetOf(vararg elements: T): TreeSet<T> = elements.toCollection(TreeSet<T>())
|
||||
|
||||
/**
|
||||
* Returns a new [SortedSet] with the given [comparator] and elements.
|
||||
*/
|
||||
//public fun <T> sortedSetOf(comparator: Comparator<in T>, vararg elements: T): TreeSet<T> = elements.toCollection(TreeSet<T>(comparator))
|
||||
|
||||
|
||||
internal fun <T> Set<T>.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 <T> Set<T>.minus(element: T): Set<T> {
|
||||
val result = LinkedHashSet<T>(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 <T> Set<T>.minus(elements: Array<out T>): Set<T> {
|
||||
val result = LinkedHashSet<T>(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 <T> Set<T>.minus(elements: Iterable<T>): Set<T> {
|
||||
val other = elements.convertToSetForSetOperationWith(this)
|
||||
if (other.isEmpty())
|
||||
return this.toSet()
|
||||
if (other is Set)
|
||||
return this.filterNotTo(LinkedHashSet<T>()) { it in other }
|
||||
val result = LinkedHashSet<T>(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 <T> Set<T>.minus(elements: Sequence<T>): Set<T> {
|
||||
val result = LinkedHashSet<T>(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 <T> Set<T>.minusElement(element: T): Set<T> {
|
||||
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 <T> Set<T>.plus(element: T): Set<T> {
|
||||
val result = LinkedHashSet<T>(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 <T> Set<T>.plus(elements: Array<out T>): Set<T> {
|
||||
val result = LinkedHashSet<T>(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 <T> Set<T>.plus(elements: Iterable<T>): Set<T> {
|
||||
val result = LinkedHashSet<T>(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 <T> Set<T>.plus(elements: Sequence<T>): Set<T> {
|
||||
val result = LinkedHashSet<T>(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 <T> Set<T>.plusElement(element: T): Set<T> {
|
||||
return plus(element)
|
||||
}
|
||||
|
||||
@@ -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 <T> Sequence<T>.windowedSequence(size: Int, step: Int, partialWindows: Boolean, reuseBuffer: Boolean): Sequence<List<T>> {
|
||||
checkWindowSizeStep(size, step)
|
||||
return Sequence { windowedIterator(iterator(), size, step, partialWindows, reuseBuffer) }
|
||||
}
|
||||
|
||||
internal fun <T> windowedIterator(iterator: Iterator<T>, size: Int, step: Int, partialWindows: Boolean, reuseBuffer: Boolean): Iterator<List<T>> {
|
||||
if (!iterator.hasNext()) return EmptyIterator
|
||||
return buildIterator<List<T>> {
|
||||
val gap = step - size
|
||||
if (gap >= 0) {
|
||||
var buffer = ArrayList<T>(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<T>(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<out E>(private val list: List<E>) : AbstractList<E>(), 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<T>(val capacity: Int): AbstractList<T>(), RandomAccess {
|
||||
init {
|
||||
require(capacity >= 0) { "ring buffer capacity should not be negative but it is $capacity" }
|
||||
}
|
||||
|
||||
private val buffer = arrayOfNulls<Any?>(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<T> = object : AbstractIterator<T>() {
|
||||
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 <T> toArray(array: Array<T>): Array<T> {
|
||||
val result: Array<T?> =
|
||||
if (array.size < this.size) array.copyOf(this.size) else array as Array<T?>
|
||||
|
||||
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<T>
|
||||
}
|
||||
|
||||
override fun toArray(): Array<Any?> {
|
||||
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 <T> Array<T>.fill(element: T, fromIndex: Int = 0, toIndex: Int = size): Unit {
|
||||
for (idx in fromIndex .. toIndex-1) {
|
||||
this[idx] = element
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,318 +16,14 @@
|
||||
|
||||
package kotlin.comparisons
|
||||
|
||||
interface Comparator<T> {
|
||||
fun compare(a: T, b: T): Int
|
||||
}
|
||||
|
||||
fun <T> Comparator(function: (a: T, b: T) -> Int): Comparator<T> {
|
||||
return object: Comparator<T> {
|
||||
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 <T> 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 <T> 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 <T, K> compareValuesBy(a: T, b: T, comparator: Comparator<in K>, 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 <T> compareValuesWith(a: T, b: T, comparator: Comparator<T>): Int = comparator.compare(a, b)
|
||||
//
|
||||
|
||||
|
||||
/**
|
||||
* Compares two nullable [Comparable] values. Null is considered less than any value.
|
||||
*/
|
||||
public fun <T : Comparable<*>> 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<Any>).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 <T> compareBy(vararg selectors: (T) -> Comparable<*>?): Comparator<T> {
|
||||
return object : Comparator<T> {
|
||||
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 <T> compareBy(crossinline selector: (T) -> Comparable<*>?): Comparator<T> {
|
||||
return object : Comparator<T> {
|
||||
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 <T, K> compareBy(comparator: Comparator<in K>, crossinline selector: (T) -> K): Comparator<T> {
|
||||
return object : Comparator<T> {
|
||||
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 <T> compareByDescending(crossinline selector: (T) -> Comparable<*>?): Comparator<T> {
|
||||
return object : Comparator<T> {
|
||||
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 <T, K> compareByDescending(comparator: Comparator<in K>, crossinline selector: (T) -> K): Comparator<T> {
|
||||
return object : Comparator<T> {
|
||||
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 <T> Comparator<T>.thenBy(crossinline selector: (T) -> Comparable<*>?): Comparator<T> {
|
||||
return object : Comparator<T> {
|
||||
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 <T, K> Comparator<T>.thenBy(comparator: Comparator<in K>, crossinline selector: (T) -> K): Comparator<T> {
|
||||
return object : Comparator<T> {
|
||||
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 <T> Comparator<T>.thenByDescending(crossinline selector: (T) -> Comparable<*>?): Comparator<T> {
|
||||
return object : Comparator<T> {
|
||||
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 <T, K> Comparator<T>.thenByDescending(comparator: Comparator<in K>, crossinline selector: (T) -> K): Comparator<T> {
|
||||
return object : Comparator<T> {
|
||||
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 <T> Comparator<T>.thenComparator(crossinline comparison: (T, T) -> Int): Comparator<T> {
|
||||
return object : Comparator<T> {
|
||||
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 <T> Comparator<T>.then(comparator: Comparator<in T>): Comparator<T> {
|
||||
return object : Comparator<T> {
|
||||
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 <T> Comparator<T>.thenDescending(comparator: Comparator<in T>): Comparator<T> {
|
||||
return object : Comparator<T> {
|
||||
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 <T: Any> nullsFirst(comparator: Comparator<in T>): Comparator<T?> {
|
||||
return object: Comparator<T?> {
|
||||
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 <T: Comparable<T>> nullsFirst(): Comparator<T?> = 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 <T: Any> nullsLast(comparator: Comparator<in T>): Comparator<T?> {
|
||||
return object: Comparator<T?> {
|
||||
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 <T: Comparable<T>> nullsLast(): Comparator<T?> = nullsLast(naturalOrder())
|
||||
|
||||
/**
|
||||
* Returns a comparator that compares [Comparable] objects in natural order.
|
||||
*/
|
||||
public fun <T: Comparable<T>> naturalOrder(): Comparator<T> = @Suppress("UNCHECKED_CAST") (NaturalOrderComparator as Comparator<T>)
|
||||
|
||||
/**
|
||||
* Returns a comparator that compares [Comparable] objects in reversed natural order.
|
||||
*/
|
||||
public fun <T: Comparable<T>> reverseOrder(): Comparator<T> = @Suppress("UNCHECKED_CAST") (ReverseOrderComparator as Comparator<T>)
|
||||
|
||||
/** Returns a comparator that imposes the reverse ordering of this comparator. */
|
||||
public fun <T> Comparator<T>.reversed(): Comparator<T> = when (this) {
|
||||
is ReversedComparator -> this.comparator
|
||||
NaturalOrderComparator -> @Suppress("UNCHECKED_CAST") (ReverseOrderComparator as Comparator<T>)
|
||||
ReverseOrderComparator -> @Suppress("UNCHECKED_CAST") (NaturalOrderComparator as Comparator<T>)
|
||||
else -> ReversedComparator(this)
|
||||
}
|
||||
|
||||
|
||||
private class ReversedComparator<T>(public val comparator: Comparator<T>): Comparator<T> {
|
||||
override fun compare(a: T, b: T): Int = comparator.compare(b, a)
|
||||
@Suppress("VIRTUAL_MEMBER_HIDDEN")
|
||||
fun reversed(): Comparator<T> = comparator
|
||||
}
|
||||
|
||||
private object NaturalOrderComparator : Comparator<Comparable<Any>> {
|
||||
override fun compare(a: Comparable<Any>, b: Comparable<Any>): Int = a.compareTo(b)
|
||||
@Suppress("VIRTUAL_MEMBER_HIDDEN")
|
||||
fun reversed(): Comparator<Comparable<Any>> = ReverseOrderComparator
|
||||
}
|
||||
|
||||
private object ReverseOrderComparator: Comparator<Comparable<Any>> {
|
||||
override fun compare(a: Comparable<Any>, b: Comparable<Any>): Int = b.compareTo(a)
|
||||
@Suppress("VIRTUAL_MEMBER_HIDDEN")
|
||||
fun reversed(): Comparator<Comparable<Any>> = 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 <T: Comparable<T>> maxOf(a: T, b: T): T {
|
||||
public actual fun <T: Comparable<T>> maxOf(a: T, b: T): T {
|
||||
return if (a >= b) a else b
|
||||
}
|
||||
|
||||
@@ -336,7 +32,7 @@ public fun <T: Comparable<T>> 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 <T: Comparable<T>> maxOf(a: T, b: T, c: T): T {
|
||||
public actual fun <T: Comparable<T>> maxOf(a: T, b: T, c: T): T {
|
||||
return maxOf(a, maxOf(b, c))
|
||||
}
|
||||
|
||||
@@ -409,7 +105,7 @@ public fun <T: Comparable<T>> 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 <T> maxOf(a: T, b: T, c: T, comparator: Comparator<in T>): 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 <T> maxOf(a: T, b: T, comparator: Comparator<in T>): 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 <T: Comparable<T>> minOf(a: T, b: T): T {
|
||||
public actual fun <T: Comparable<T>> minOf(a: T, b: T): T {
|
||||
return if (a <= b) a else b
|
||||
}
|
||||
|
||||
@@ -489,7 +168,7 @@ public fun <T: Comparable<T>> 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 <T: Comparable<T>> minOf(a: T, b: T, c: T): T {
|
||||
public actual fun <T: Comparable<T>> minOf(a: T, b: T, c: T): T {
|
||||
return minOf(a, minOf(b, c))
|
||||
}
|
||||
|
||||
@@ -561,7 +240,7 @@ public fun <T: Comparable<T>> 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 <T> minOf(a: T, b: T, c: T, comparator: Comparator<in T>): 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 <T> minOf(a: T, b: T, comparator: Comparator<in T>): T {
|
||||
return if (comparator.compare(a, b) <= 0) a else b
|
||||
}
|
||||
|
||||
@@ -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<ContinuationInterceptor>
|
||||
|
||||
/**
|
||||
* 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 <T> interceptContinuation(continuation: Continuation<T>): Continuation<T>
|
||||
}
|
||||
@@ -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 <E : Element> get(key: Key<E>): 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 <R> 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<E : Element>
|
||||
}
|
||||
@@ -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<in T> {
|
||||
/**
|
||||
* 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
|
||||
@@ -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 <R, T> (suspend R.() -> T).startCoroutine(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
) {
|
||||
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 <T> (suspend () -> T).startCoroutine(
|
||||
completion: Continuation<T>
|
||||
) {
|
||||
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 <R, T> (suspend R.() -> T).createCoroutine(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> = 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 <T> (suspend () -> T).createCoroutine(
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> = 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 <T> suspendCoroutine(crossinline block: (Continuation<T>) -> Unit): T =
|
||||
suspendCoroutineOrReturn { c: Continuation<T> ->
|
||||
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<Any?>).resume(result)
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
completion.resumeWithException(t)
|
||||
}
|
||||
}
|
||||
@@ -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 <E : Element> get(key: Key<E>): E? =
|
||||
if (this.key === key) this as E else null
|
||||
|
||||
public override fun <R> 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 <E : Element> get(key: Key<E>): E? = null
|
||||
public override fun <R> 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 <E : Element> get(key: Key<E>): 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 <R> 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-30
@@ -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 <T> suspendCoroutineOrReturn(crossinline block: (Continuation<T>) -> Any?): T =
|
||||
returnIfSuspended<T>(block(normalizeContinuation<T>(getContinuation<T>())))
|
||||
|
||||
/**
|
||||
* 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 <T> (suspend () -> T).createCoroutineUnchecked(
|
||||
public actual fun <T> (suspend () -> T).createCoroutineUnchecked(
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> =
|
||||
if (this !is CoroutineImpl)
|
||||
@@ -78,7 +52,7 @@ public fun <T> (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 <R, T> (suspend R.() -> T).createCoroutineUnchecked(
|
||||
public actual fun <R, T> (suspend R.() -> T).createCoroutineUnchecked(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> =
|
||||
@@ -122,7 +96,7 @@ private /*inline*/ fun <T> buildContinuationByInvokeCall(
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrReturn(
|
||||
public actual inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrReturn(
|
||||
completion: Continuation<T>
|
||||
): Any? = (this as Function1<Continuation<T>, Any?>).invoke(completion)
|
||||
|
||||
@@ -135,7 +109,7 @@ public inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrReturn(
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedOrReturn(
|
||||
public actual inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedOrReturn(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Any? = (this as Function2<R, Continuation<T>, Any?>).invoke(receiver, completion)
|
||||
@@ -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<in T> internal actual constructor(
|
||||
private val delegate: Continuation<T>, initialResult: Any?) : Continuation<T> {
|
||||
|
||||
@PublishedApi
|
||||
internal actual constructor(delegate: Continuation<T>) : 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <T> buildSequence(builderAction: suspend SequenceBuilder<T>.() -> Unit): Sequence<T> = Sequence { buildIterator(builderAction) }
|
||||
|
||||
/**
|
||||
* Builds an [Iterator] lazily yielding values one by one.
|
||||
*
|
||||
* @sample samples.collections.Sequences.Building.buildIterator
|
||||
*/
|
||||
public fun <T> buildIterator(builderAction: suspend SequenceBuilder<T>.() -> Unit): Iterator<T> {
|
||||
val iterator = SequenceBuilderIterator<T>()
|
||||
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<in T> 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<T>)
|
||||
|
||||
/**
|
||||
* Yields a collections of values to the [Iterator] being built.
|
||||
*
|
||||
* @sample samples.collections.Sequences.Building.buildSequenceYieldAll
|
||||
*/
|
||||
public suspend fun yieldAll(elements: Iterable<T>) {
|
||||
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<T>) = 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<T> : SequenceBuilder<T>(), Iterator<T>, Continuation<Unit> {
|
||||
private var state = State_NotReady
|
||||
private var nextValue: T? = null
|
||||
private var nextIterator: Iterator<T>? = null
|
||||
var nextStep: Continuation<Unit>? = 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<T>) {
|
||||
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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -24,7 +24,7 @@ public fun<T> 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<T> 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?
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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 <T: Any> notNull(): ReadWriteProperty<Any?, T> = 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 <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit):
|
||||
ReadWriteProperty<Any?, T> = object : ObservableProperty<T>(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 <T> vetoable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean):
|
||||
ReadWriteProperty<Any?, T> = object : ObservableProperty<T>(initialValue) {
|
||||
override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = onChange(property, oldValue, newValue)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private class NotNullVar<T: Any>() : ReadWriteProperty<Any?, T> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<in R, out T> {
|
||||
/**
|
||||
* 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<in R, T> {
|
||||
/**
|
||||
* 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)
|
||||
}
|
||||
@@ -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<T>(initialValue: T) : ReadWriteProperty<Any?, T> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -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: Comparable<T>> 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: Comparable<T>> 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: Comparable<T>> 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: Comparable<T>> T.coerceIn(range: ClosedRange<T>): 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>): 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>): 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<T: Comparable<T>> : ClosedRange<T> {
|
||||
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<T: Comparable<T>> (
|
||||
override val start: T,
|
||||
override val endInclusive: T
|
||||
): ClosedRange<T> {
|
||||
|
||||
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<Double> {
|
||||
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: Comparable<T>> T.rangeTo(that: T): ClosedRange<T> = 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<Double> = ClosedDoubleRange(this, that)
|
||||
|
||||
/**
|
||||
* Creates a range from this [Float] value to the specified [other] value.
|
||||
*
|
||||
|
||||
@@ -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<Int>.contains(value: Byte): Boolean {
|
||||
return contains(value.toInt())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Long>.contains(value: Byte): Boolean {
|
||||
return contains(value.toLong())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Short>.contains(value: Byte): Boolean {
|
||||
return contains(value.toShort())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Double>.contains(value: Byte): Boolean {
|
||||
return contains(value.toDouble())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Float>.contains(value: Byte): Boolean {
|
||||
return contains(value.toFloat())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Int>.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<Long>.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<Byte>.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<Short>.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<Float>.contains(value: Double): Boolean {
|
||||
return contains(value.toFloat())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Int>.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<Long>.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<Byte>.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<Short>.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<Double>.contains(value: Float): Boolean {
|
||||
return contains(value.toDouble())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Long>.contains(value: Int): Boolean {
|
||||
return contains(value.toLong())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Byte>.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<Short>.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<Double>.contains(value: Int): Boolean {
|
||||
return contains(value.toDouble())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Float>.contains(value: Int): Boolean {
|
||||
return contains(value.toFloat())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Int>.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<Byte>.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<Short>.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<Double>.contains(value: Long): Boolean {
|
||||
return contains(value.toDouble())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Float>.contains(value: Long): Boolean {
|
||||
return contains(value.toFloat())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Int>.contains(value: Short): Boolean {
|
||||
return contains(value.toInt())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Long>.contains(value: Short): Boolean {
|
||||
return contains(value.toLong())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Byte>.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<Double>.contains(value: Short): Boolean {
|
||||
return contains(value.toDouble())
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified [value] belongs to this range.
|
||||
*/
|
||||
public operator fun ClosedRange<Float>.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: Comparable<T>> T.coerceIn(range: ClosedFloatingPointRange<T>): 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
|
||||
}
|
||||
}
|
||||
@@ -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<out T> {
|
||||
/**
|
||||
* 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<T>
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 : Appendable> 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 <T> 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
|
||||
}
|
||||
|
||||
@@ -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}")
|
||||
}
|
||||
|
||||
@@ -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<String>.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()
|
||||
}
|
||||
@@ -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<MatchGroup?> {
|
||||
|
||||
/** 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<String>
|
||||
|
||||
/**
|
||||
* 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<String> = match.groupValues.subList(1, match.groupValues.size)
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ private fun fromInt(value: Int): Set<RegexOption> =
|
||||
/**
|
||||
* 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<RegexOption>): this(Pattern(pattern, ensureUnicodeCase(options.toInt())))
|
||||
actual constructor(pattern: String, options: Set<RegexOption>): 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<RegexOption> = fromInt(nativePattern.flags)
|
||||
actual val options: Set<RegexOption> = 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<MatchResult>
|
||||
actual fun findAll(input: CharSequence, startIndex: Int): Sequence<MatchResult>
|
||||
= 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<String> {
|
||||
actual fun split(input: CharSequence, limit: Int): List<String> {
|
||||
require(limit >= 0, { "Limit must be non-negative, but was $limit." } )
|
||||
if (input.isEmpty()) {
|
||||
return listOf("")
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
@@ -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 <T:Any> 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 <T:Any> 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 <T:Any> 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 <T:Any> 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())
|
||||
@@ -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 <R> 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, R> 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 <T, R> 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> 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> 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, R> 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)
|
||||
}
|
||||
}
|
||||
@@ -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<out A, out B>(
|
||||
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, B> A.to(that: B): Pair<A, B> = Pair(this, that)
|
||||
|
||||
/**
|
||||
* Converts this pair into a list.
|
||||
*/
|
||||
public fun <T> Pair<T, T>.toList(): List<T> = 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<out A, out B, out C>(
|
||||
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 <T> Triple<T, T, T>.toList(): List<T> = listOf(first, second, third)
|
||||
@@ -30,7 +30,7 @@ fun parseLine(line: String, separator: Char) : List<String> {
|
||||
(ch == '\n') || (ch == '\r') -> {}
|
||||
(ch == separator) && (quotes % 2 == 0) -> {
|
||||
result.add(builder.toString())
|
||||
builder.length = 0
|
||||
builder.setLength(0)
|
||||
}
|
||||
else -> builder.append(ch)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user