Common stdlib

- adds actual matching expect declarations
- removes duplicates
- rewrite collections
- add MPP and experimental compiler options
This commit is contained in:
Pavel Punegov
2018-05-16 18:39:49 +03:00
committed by Pavel Punegov
parent c807fca8cb
commit 374397d03f
72 changed files with 2042 additions and 27364 deletions
+5
View File
@@ -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"
@@ -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)
@@ -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))
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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.
@@ -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)
}
}
+67 -59
View File
@@ -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)
}
}
+3 -162
View File
@@ -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)
+12 -12
View File
@@ -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
}
}
@@ -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
@@ -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)
}
}
}
@@ -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
+3 -3
View File
@@ -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
+110 -121
View File
@@ -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
}
+7 -7
View File
@@ -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)
}
}
+21 -21
View File
@@ -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)
}