stdlib-jvm: move JVM specific sources, add actual modifier where required
Update copyright path after moving JVM sources
This commit is contained in:
@@ -1,23 +0,0 @@
|
||||
@file:JvmVersion
|
||||
package kotlin.collections
|
||||
|
||||
import java.util.AbstractCollection
|
||||
|
||||
/**
|
||||
* Provides a skeletal implementation of the [MutableCollection] interface.
|
||||
*
|
||||
* @param E the type of elements contained in the collection. The collection is invariant on its element type.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
public abstract class AbstractMutableCollection<E> protected constructor() : MutableCollection<E>, AbstractCollection<E>() {
|
||||
/**
|
||||
* Adds the specified element to the collection.
|
||||
*
|
||||
* 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 collection does not support duplicates
|
||||
* and the element is already contained in the collection.
|
||||
*/
|
||||
abstract override fun add(element: E): Boolean
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
@file:JvmVersion
|
||||
package kotlin.collections
|
||||
|
||||
import java.util.AbstractList
|
||||
|
||||
/**
|
||||
* Provides a skeletal implementation of the [MutableList] interface.
|
||||
*
|
||||
* @param E the type of elements contained in the list. The list is invariant on its element type.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
public abstract class AbstractMutableList<E> protected constructor() : MutableList<E>, AbstractList<E>() {
|
||||
/**
|
||||
* Replaces the element at the specified position in this list with the specified element.
|
||||
*
|
||||
* 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 element previously at the specified position.
|
||||
*/
|
||||
abstract override fun set(index: Int, element: E): E
|
||||
/**
|
||||
* Removes an element at the specified [index] from the list.
|
||||
*
|
||||
* 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 element that has been removed.
|
||||
*/
|
||||
abstract override fun removeAt(index: Int): E
|
||||
/**
|
||||
* Inserts an element into the list at the specified [index].
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
abstract override fun add(index: Int, element: E)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
@file:JvmVersion
|
||||
package kotlin.collections
|
||||
|
||||
import java.util.AbstractMap
|
||||
|
||||
/**
|
||||
* 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")
|
||||
public abstract class AbstractMutableMap<K, V> protected constructor() : MutableMap<K, V>, AbstractMap<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.
|
||||
*/
|
||||
abstract override fun put(key: K, value: V): V?
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
@file:JvmVersion
|
||||
package kotlin.collections
|
||||
|
||||
import java.util.AbstractSet
|
||||
|
||||
/**
|
||||
* 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")
|
||||
public abstract class AbstractMutableSet<E> protected constructor() : MutableSet<E>, AbstractSet<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.
|
||||
*/
|
||||
abstract override fun add(element: E): Boolean
|
||||
}
|
||||
@@ -1,57 +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.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("ArraysKt")
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
import java.nio.charset.Charset
|
||||
|
||||
|
||||
/**
|
||||
* Returns the array if it's not `null`, or an empty array otherwise.
|
||||
* @sample samples.collections.Arrays.Usage.arrayOrEmpty
|
||||
*/
|
||||
public inline fun <reified T> Array<out T>?.orEmpty(): Array<out T> = this ?: emptyArray<T>()
|
||||
|
||||
/**
|
||||
* Converts the contents of this byte array to a string using the specified [charset].
|
||||
* @sample samples.text.Strings.stringToByteArray
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun ByteArray.toString(charset: Charset): String = String(this, charset)
|
||||
|
||||
/**
|
||||
* Returns a *typed* array containing all of the elements of this collection.
|
||||
*
|
||||
* Allocates an array of runtime type `T` having its size equal to the size of this collection
|
||||
* and populates the array with the elements of this collection.
|
||||
* @sample samples.collections.Collections.Collections.collectionToTypedArray
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public inline fun <reified T> Collection<T>.toTypedArray(): Array<T> {
|
||||
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
|
||||
val thisCollection = this as java.util.Collection<T>
|
||||
return thisCollection.toArray(arrayOfNulls<T>(0)) as Array<T>
|
||||
}
|
||||
|
||||
/** Internal unsafe construction of array based on reference array type */
|
||||
internal fun <T> arrayOfNulls(reference: Array<T>, size: Int): Array<T> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return java.lang.reflect.Array.newInstance(reference.javaClass.componentType, size) as Array<T>
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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 java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
class ArraysUtilJVM {
|
||||
static <T> List<T> asList(T[] array) {
|
||||
return Arrays.asList(array);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("CollectionsKt")
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
import kotlin.*
|
||||
|
||||
/**
|
||||
* Returns an immutable list containing only the specified object [element].
|
||||
* The returned list is serializable.
|
||||
* @sample samples.collections.Collections.Lists.singletonReadOnlyList
|
||||
*/
|
||||
@JvmVersion
|
||||
public fun <T> listOf(element: T): List<T> = java.util.Collections.singletonList(element)
|
||||
|
||||
|
||||
/**
|
||||
* Returns a list containing the elements returned by this enumeration
|
||||
* in the order they are returned by the enumeration.
|
||||
* @sample samples.collections.Collections.Lists.listFromEnumeration
|
||||
*/
|
||||
@JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <T> java.util.Enumeration<T>.toList(): List<T> = java.util.Collections.list(this)
|
||||
|
||||
|
||||
@JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
internal inline fun copyToArrayImpl(collection: Collection<*>): Array<Any?> =
|
||||
kotlin.jvm.internal.collectionToArray(collection)
|
||||
|
||||
@JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
internal inline fun <T> copyToArrayImpl(collection: Collection<*>, array: Array<T>): Array<T> =
|
||||
kotlin.jvm.internal.collectionToArray(collection, array as Array<Any?>) as Array<T>
|
||||
|
||||
// copies typed varargs array to array of objects
|
||||
@JvmVersion
|
||||
internal fun <T> Array<out T>.copyToArrayOfAny(isVarargs: Boolean): Array<Any?> =
|
||||
if (isVarargs && this.javaClass == Array<Any?>::class.java)
|
||||
// if the array came from varargs and already is array of Any, copying isn't required
|
||||
@Suppress("UNCHECKED_CAST") (this as Array<Any?>)
|
||||
else
|
||||
java.util.Arrays.copyOf(this, this.size, Array<Any?>::class.java)
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmName("GroupingKt")
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
|
||||
/**
|
||||
* 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")
|
||||
@JvmVersion
|
||||
public fun <T, K> Grouping<T, K>.eachCount(): Map<K, Int> =
|
||||
// fold(0) { acc, e -> acc + 1 } optimized for boxing
|
||||
foldTo(destination = mutableMapOf(),
|
||||
initialValueSelector = { _, _ -> kotlin.jvm.internal.Ref.IntRef() },
|
||||
operation = { _, acc, _ -> acc.apply { element += 1 } })
|
||||
.mapValuesInPlace { it.value.element }
|
||||
|
||||
/*
|
||||
/**
|
||||
* Groups elements from the [Grouping] source by key and sums values provided by the [valueSelector] function for elements in each group.
|
||||
*
|
||||
* @return a [Map] associating the key of each group with the sum of elements in the group.
|
||||
*/
|
||||
@SinceKotlin("1.X")
|
||||
@JvmVersion
|
||||
public inline fun <T, K> Grouping<T, K>.eachSumOf(valueSelector: (T) -> Int): Map<K, Int> =
|
||||
// fold(0) { acc, e -> acc + valueSelector(e)} optimized for boxing
|
||||
foldTo( destination = mutableMapOf(),
|
||||
initialValueSelector = { _, _ -> kotlin.jvm.internal.Ref.IntRef() },
|
||||
operation = { _, acc, e -> acc.apply { element += valueSelector(e) } })
|
||||
.mapValuesInPlace { it.value.element }
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@JvmVersion
|
||||
@PublishedApi
|
||||
@kotlin.internal.InlineOnly
|
||||
@Suppress("UNCHECKED_CAST") // tricks with erased generics go here, do not repeat on reified platforms
|
||||
internal inline fun <K, V, R> MutableMap<K, V>.mapValuesInPlace(f: (Map.Entry<K, V>) -> R): MutableMap<K, R> {
|
||||
entries.forEach {
|
||||
(it as MutableMap.MutableEntry<K, R>).setValue(f(it))
|
||||
}
|
||||
return (this as MutableMap<K, R>)
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("CollectionsKt")
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
/**
|
||||
* Creates an [Iterator] for an [java.util.Enumeration], allowing to use it in `for` loops.
|
||||
* @sample samples.collections.Iterators.iteratorForEnumeration
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
public operator fun <T> java.util.Enumeration<T>.iterator(): Iterator<T> = object : Iterator<T> {
|
||||
override fun hasNext(): Boolean = hasMoreElements()
|
||||
|
||||
public override fun next(): T = nextElement()
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("MapsKt")
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
import java.util.Comparator
|
||||
import java.util.LinkedHashMap
|
||||
import java.util.Properties
|
||||
import java.util.SortedMap
|
||||
import java.util.TreeMap
|
||||
import java.util.concurrent.ConcurrentMap
|
||||
|
||||
|
||||
/**
|
||||
* Returns an immutable map, mapping only the specified key to the
|
||||
* specified value.
|
||||
*
|
||||
* The returned map is serializable.
|
||||
*
|
||||
* @sample samples.collections.Maps.Instantiation.mapFromPairs
|
||||
*/
|
||||
@JvmVersion
|
||||
public fun <K, V> mapOf(pair: Pair<K, V>): Map<K, V> = java.util.Collections.singletonMap(pair.first, pair.second)
|
||||
|
||||
|
||||
/**
|
||||
* Concurrent getOrPut, that is safe for concurrent maps.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This method guarantees not to put the value into the map if the key is already there,
|
||||
* but the [defaultValue] function may be invoked even if the key is already in the map.
|
||||
*/
|
||||
public inline fun <K, V> ConcurrentMap<K, V>.getOrPut(key: K, defaultValue: () -> V): V {
|
||||
// Do not use computeIfAbsent on JVM8 as it would change locking behavior
|
||||
return this.get(key) ?:
|
||||
defaultValue().let { default -> this.putIfAbsent(key, default) ?: default }
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts this [Map] to a [SortedMap] so iteration order will be in key order.
|
||||
*
|
||||
* @sample samples.collections.Maps.Transformations.mapToSortedMap
|
||||
*/
|
||||
public fun <K : Comparable<K>, V> Map<out K, V>.toSortedMap(): SortedMap<K, V> = TreeMap(this)
|
||||
|
||||
/**
|
||||
* Converts this [Map] to a [SortedMap] using the given [comparator] so that iteration order will be in the order
|
||||
* defined by the comparator.
|
||||
*
|
||||
* @sample samples.collections.Maps.Transformations.mapToSortedMapWithComparator
|
||||
*/
|
||||
public fun <K, V> Map<out K, V>.toSortedMap(comparator: Comparator<in K>): SortedMap<K, V>
|
||||
= TreeMap<K, V>(comparator).apply { putAll(this@toSortedMap) }
|
||||
|
||||
/**
|
||||
* Returns a new [SortedMap] with the specified contents, given as a list of pairs
|
||||
* where the first value is the key and the second is the value.
|
||||
*
|
||||
* @sample samples.collections.Maps.Instantiation.sortedMapFromPairs
|
||||
*/
|
||||
public fun <K : Comparable<K>, V> sortedMapOf(vararg pairs: Pair<K, V>): SortedMap<K, V>
|
||||
= TreeMap<K, V>().apply { putAll(pairs) }
|
||||
|
||||
|
||||
/**
|
||||
* Converts this [Map] to a [Properties] object.
|
||||
*
|
||||
* @sample samples.collections.Maps.Transformations.mapToProperties
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Map<String, String>.toProperties(): Properties
|
||||
= Properties().apply { putAll(this@toProperties) }
|
||||
|
||||
|
||||
// creates a singleton copy of map, if there is specialization available in target platform, otherwise returns itself
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
internal inline fun <K, V> Map<K, V>.toSingletonMapOrSelf(): Map<K, V> = toSingletonMap()
|
||||
|
||||
// creates a singleton copy of map
|
||||
@kotlin.jvm.JvmVersion
|
||||
internal fun <K, V> Map<out K, V>.toSingletonMap(): Map<K, V>
|
||||
= with (entries.iterator().next()) { java.util.Collections.singletonMap(key, value) }
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("CollectionsKt")
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
|
||||
@Deprecated("Use sortWith(comparator) instead.", ReplaceWith("this.sortWith(comparator)"), level = DeprecationLevel.ERROR)
|
||||
@JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
public inline fun <T> MutableList<T>.sort(comparator: Comparator<in T>): Unit = throw NotImplementedError()
|
||||
|
||||
@Deprecated("Use sortWith(Comparator(comparison)) instead.", ReplaceWith("this.sortWith(Comparator(comparison))"), level = DeprecationLevel.ERROR)
|
||||
@JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
public inline fun <T> MutableList<T>.sort(comparison: (T, T) -> Int): Unit = throw NotImplementedError()
|
||||
|
||||
|
||||
/**
|
||||
* Sorts elements in the list in-place according to their natural sort order.
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
public fun <T : Comparable<T>> MutableList<T>.sort(): Unit {
|
||||
if (size > 1) java.util.Collections.sort(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts elements in the list in-place according to the order specified with [comparator].
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
public fun <T> MutableList<T>.sortWith(comparator: Comparator<in T>): Unit {
|
||||
if (size > 1) java.util.Collections.sort(this, comparator)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the list with the provided [value].
|
||||
*
|
||||
* Each element in the list gets replaced with the [value].
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
@SinceKotlin("1.2")
|
||||
public inline fun <T> MutableList<T>.fill(value: T) {
|
||||
java.util.Collections.fill(this, value)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Randomly shuffles elements in this mutable list.
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
@SinceKotlin("1.2")
|
||||
public inline fun <T> MutableList<T>.shuffle() {
|
||||
java.util.Collections.shuffle(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Randomly shuffles elements in this mutable list using the specified [random] instance as the source of randomness.
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
@SinceKotlin("1.2")
|
||||
public inline fun <T> MutableList<T>.shuffle(random: java.util.Random) {
|
||||
java.util.Collections.shuffle(this, random)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new list with the elements of this list randomly shuffled.
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
@SinceKotlin("1.2")
|
||||
public fun <T> Iterable<T>.shuffled(): List<T> = toMutableList().apply { shuffle() }
|
||||
|
||||
/**
|
||||
* Returns a new list with the elements of this list randomly shuffled
|
||||
* using the specified [random] instance as the source of randomness.
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
@SinceKotlin("1.2")
|
||||
public fun <T> Iterable<T>.shuffled(random: java.util.Random): List<T> = toMutableList().apply { shuffle(random) }
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("SequencesKt")
|
||||
|
||||
package kotlin.sequences
|
||||
|
||||
import kotlin.*
|
||||
|
||||
/**
|
||||
* Creates a sequence that returns all values from this enumeration. The sequence is constrained to be iterated only once.
|
||||
* @sample samples.collections.Sequences.Building.sequenceFromEnumeration
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun<T> java.util.Enumeration<T>.asSequence(): Sequence<T> = this.iterator().asSequence()
|
||||
|
||||
|
||||
@kotlin.jvm.JvmVersion
|
||||
internal class ConstrainedOnceSequence<T>(sequence: Sequence<T>) : Sequence<T> {
|
||||
private val sequenceRef = java.util.concurrent.atomic.AtomicReference(sequence)
|
||||
|
||||
override fun iterator(): Iterator<T> {
|
||||
val sequence = sequenceRef.getAndSet(null) ?: throw IllegalStateException("This sequence can be consumed only once.")
|
||||
return sequence.iterator()
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("SetsKt")
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
|
||||
/**
|
||||
* Returns an immutable set containing only the specified object [element].
|
||||
* The returned set is serializable.
|
||||
*/
|
||||
@JvmVersion
|
||||
public fun <T> setOf(element: T): Set<T> = java.util.Collections.singleton(element)
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new [java.util.SortedSet] with the given elements.
|
||||
*/
|
||||
@JvmVersion
|
||||
public fun <T> sortedSetOf(vararg elements: T): java.util.TreeSet<T> = elements.toCollection(java.util.TreeSet<T>())
|
||||
|
||||
/**
|
||||
* Returns a new [java.util.SortedSet] with the given [comparator] and elements.
|
||||
*/
|
||||
@JvmVersion
|
||||
public fun <T> sortedSetOf(comparator: Comparator<in T>, vararg elements: T): java.util.TreeSet<T> = elements.toCollection(java.util.TreeSet<T>(comparator))
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
@SinceKotlin("1.1") public typealias RandomAccess = java.util.RandomAccess
|
||||
|
||||
|
||||
@SinceKotlin("1.1") public typealias ArrayList<E> = java.util.ArrayList<E>
|
||||
@SinceKotlin("1.1") public typealias LinkedHashMap<K, V> = java.util.LinkedHashMap<K, V>
|
||||
@SinceKotlin("1.1") public typealias HashMap<K, V> = java.util.HashMap<K, V>
|
||||
@SinceKotlin("1.1") public typealias LinkedHashSet<E> = java.util.LinkedHashSet<E>
|
||||
@SinceKotlin("1.1") public typealias HashSet<E> = java.util.HashSet<E>
|
||||
|
||||
@@ -1,82 +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.
|
||||
*/
|
||||
|
||||
@file:JvmVersion
|
||||
@file:JvmName("LocksKt")
|
||||
package kotlin.concurrent
|
||||
|
||||
import java.util.concurrent.locks.Lock
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
/**
|
||||
* Executes the given [action] under this lock.
|
||||
* @return the return value of the action.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <T> Lock.withLock(action: () -> T): T {
|
||||
lock()
|
||||
try {
|
||||
return action()
|
||||
} finally {
|
||||
unlock()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given [action] under the read lock of this lock.
|
||||
* @return the return value of the action.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <T> ReentrantReadWriteLock.read(action: () -> T): T {
|
||||
val rl = readLock()
|
||||
rl.lock()
|
||||
try {
|
||||
return action()
|
||||
} finally {
|
||||
rl.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given [action] under the write lock of this lock.
|
||||
*
|
||||
* The function does upgrade from read to write lock if needed, but this upgrade is not atomic
|
||||
* as such upgrade is not supported by [ReentrantReadWriteLock].
|
||||
* In order to do such upgrade this function first releases all read locks held by this thread,
|
||||
* then acquires write lock, and after releasing it acquires read locks back again.
|
||||
*
|
||||
* Therefore if the [action] inside write lock has been initiated by checking some condition,
|
||||
* the condition must be rechecked inside the [action] to avoid possible races.
|
||||
*
|
||||
* @return the return value of the action.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <T> ReentrantReadWriteLock.write(action: () -> T): T {
|
||||
val rl = readLock()
|
||||
|
||||
val readCount = if (writeHoldCount == 0) readHoldCount else 0
|
||||
repeat(readCount) { rl.unlock() }
|
||||
|
||||
val wl = writeLock()
|
||||
wl.lock()
|
||||
try {
|
||||
return action()
|
||||
} finally {
|
||||
repeat(readCount) { rl.lock() }
|
||||
wl.unlock()
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
@file:JvmVersion
|
||||
@file:JvmName("ThreadsKt")
|
||||
package kotlin.concurrent
|
||||
|
||||
/**
|
||||
* Creates a thread that runs the specified [block] of code.
|
||||
*
|
||||
* @param start if `true`, the thread is immediately started.
|
||||
* @param isDaemon if `true`, the thread is created as a daemon thread. The Java Virtual Machine exits when
|
||||
* the only threads running are all daemon threads.
|
||||
* @param contextClassLoader the class loader to use for loading classes and resources in this thread.
|
||||
* @param name the name of the thread.
|
||||
* @param priority the priority of the thread.
|
||||
*/
|
||||
public fun thread(start: Boolean = true, isDaemon: Boolean = false, contextClassLoader: ClassLoader? = null, name: String? = null, priority: Int = -1, block: () -> Unit): Thread {
|
||||
val thread = object : Thread() {
|
||||
public override fun run() {
|
||||
block()
|
||||
}
|
||||
}
|
||||
if (isDaemon)
|
||||
thread.isDaemon = true
|
||||
if (priority > 0)
|
||||
thread.priority = priority
|
||||
if (name != null)
|
||||
thread.name = name
|
||||
if (contextClassLoader != null)
|
||||
thread.contextClassLoader = contextClassLoader
|
||||
if (start)
|
||||
thread.start()
|
||||
return thread
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value in the current thread's copy of this
|
||||
* thread-local variable or replaces the value with the result of calling
|
||||
* [default] function in case if that value was `null`.
|
||||
*
|
||||
* If the variable has no value for the current thread,
|
||||
* it is first initialized to the value returned
|
||||
* by an invocation of the [ThreadLocal.initialValue] method.
|
||||
* Then if it is still `null`, the provided [default] function is called and its result
|
||||
* is stored for the current thread and then returned.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <T: Any> ThreadLocal<T>.getOrSet(default: () -> T): T {
|
||||
return get() ?: default().also(this::set)
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
@file:JvmVersion
|
||||
@file:JvmName("TimersKt")
|
||||
package kotlin.concurrent
|
||||
|
||||
import java.util.Date
|
||||
import java.util.Timer
|
||||
import java.util.TimerTask
|
||||
|
||||
/**
|
||||
* Schedules an [action] to be executed after the specified [delay] (expressed in milliseconds).
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Timer.schedule(delay: Long, crossinline action: TimerTask.() -> Unit): TimerTask {
|
||||
val task = timerTask(action)
|
||||
schedule(task, delay)
|
||||
return task
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules an [action] to be executed at the specified [time].
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Timer.schedule(time: Date, crossinline action: TimerTask.() -> Unit): TimerTask {
|
||||
val task = timerTask(action)
|
||||
schedule(task, time)
|
||||
return task
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules an [action] to be executed periodically, starting after the specified [delay] (expressed
|
||||
* in milliseconds) and with the interval of [period] milliseconds between the end of the previous task
|
||||
* and the start of the next one.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Timer.schedule(delay: Long, period: Long, crossinline action: TimerTask.() -> Unit): TimerTask {
|
||||
val task = timerTask(action)
|
||||
schedule(task, delay, period)
|
||||
return task
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules an [action] to be executed periodically, starting at the specified [time] and with the
|
||||
* interval of [period] milliseconds between the end of the previous task and the start of the next one.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Timer.schedule(time: Date, period: Long, crossinline action: TimerTask.() -> Unit): TimerTask {
|
||||
val task = timerTask(action)
|
||||
schedule(task, time, period)
|
||||
return task
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules an [action] to be executed periodically, starting after the specified [delay] (expressed
|
||||
* in milliseconds) and with the interval of [period] milliseconds between the start of the previous task
|
||||
* and the start of the next one.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Timer.scheduleAtFixedRate(delay: Long, period: Long, crossinline action: TimerTask.() -> Unit): TimerTask {
|
||||
val task = timerTask(action)
|
||||
scheduleAtFixedRate(task, delay, period)
|
||||
return task
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules an [action] to be executed periodically, starting at the specified [time] and with the
|
||||
* interval of [period] milliseconds between the start of the previous task and the start of the next one.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Timer.scheduleAtFixedRate(time: Date, period: Long, crossinline action: TimerTask.() -> Unit): TimerTask {
|
||||
val task = timerTask(action)
|
||||
scheduleAtFixedRate(task, time, period)
|
||||
return task
|
||||
}
|
||||
|
||||
|
||||
// exposed as public
|
||||
@PublishedApi
|
||||
internal fun timer(name: String?, daemon: Boolean) = if (name == null) Timer(daemon) else Timer(name, daemon)
|
||||
|
||||
/**
|
||||
* Creates a timer that executes the specified [action] periodically, starting after the specified [initialDelay]
|
||||
* (expressed in milliseconds) and with the interval of [period] milliseconds between the end of the previous task
|
||||
* and the start of the next one.
|
||||
*
|
||||
* @param name the name to use for the thread which is running the timer.
|
||||
* @param daemon if `true`, the thread is started as a daemon thread (the VM will exit when only daemon threads are running).
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun timer(name: String? = null, daemon: Boolean = false, initialDelay: Long = 0.toLong(), period: Long, crossinline action: TimerTask.() -> Unit): Timer {
|
||||
val timer = timer(name, daemon)
|
||||
timer.schedule(initialDelay, period, action)
|
||||
return timer
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a timer that executes the specified [action] periodically, starting at the specified [startAt] date
|
||||
* and with the interval of [period] milliseconds between the end of the previous task and the start of the next one.
|
||||
*
|
||||
* @param name the name to use for the thread which is running the timer.
|
||||
* @param daemon if `true`, the thread is started as a daemon thread (the VM will exit when only daemon threads are running).
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun timer(name: String? = null, daemon: Boolean = false, startAt: Date, period: Long, crossinline action: TimerTask.() -> Unit): Timer {
|
||||
val timer = timer(name, daemon)
|
||||
timer.schedule(startAt, period, action)
|
||||
return timer
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a timer that executes the specified [action] periodically, starting after the specified [initialDelay]
|
||||
* (expressed in milliseconds) and with the interval of [period] milliseconds between the start of the previous task
|
||||
* and the start of the next one.
|
||||
*
|
||||
* @param name the name to use for the thread which is running the timer.
|
||||
* @param daemon if `true`, the thread is started as a daemon thread (the VM will exit when only daemon threads are running).
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun fixedRateTimer(name: String? = null, daemon: Boolean = false, initialDelay: Long = 0.toLong(), period: Long, crossinline action: TimerTask.() -> Unit): Timer {
|
||||
val timer = timer(name, daemon)
|
||||
timer.scheduleAtFixedRate(initialDelay, period, action)
|
||||
return timer
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a timer that executes the specified [action] periodically, starting at the specified [startAt] date
|
||||
* and with the interval of [period] milliseconds between the start of the previous task and the start of the next one.
|
||||
*
|
||||
* @param name the name to use for the thread which is running the timer.
|
||||
* @param daemon if `true`, the thread is started as a daemon thread (the VM will exit when only daemon threads are running).
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun fixedRateTimer(name: String? = null, daemon: Boolean = false, startAt: Date, period: Long, crossinline action: TimerTask.() -> Unit): Timer {
|
||||
val timer = timer(name, daemon)
|
||||
timer.scheduleAtFixedRate(startAt, period, action)
|
||||
return timer
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the specified [action] in a [TimerTask].
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun timerTask(crossinline action: TimerTask.() -> Unit): TimerTask = object : TimerTask() {
|
||||
override fun run() = action()
|
||||
}
|
||||
@@ -1,92 +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.
|
||||
*/
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
package kotlin.coroutines.experimental
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||
import kotlin.*
|
||||
import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED
|
||||
|
||||
@PublishedApi
|
||||
internal class SafeContinuation<in T>
|
||||
internal constructor(
|
||||
private val delegate: Continuation<T>,
|
||||
initialResult: Any?
|
||||
) : Continuation<T> {
|
||||
|
||||
@PublishedApi
|
||||
internal constructor(delegate: Continuation<T>) : this(delegate, UNDECIDED)
|
||||
|
||||
public override val context: CoroutineContext
|
||||
get() = delegate.context
|
||||
|
||||
@Volatile
|
||||
private var result: Any? = initialResult
|
||||
|
||||
companion object {
|
||||
private val UNDECIDED: Any? = Any()
|
||||
private val RESUMED: Any? = Any()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@JvmStatic
|
||||
private val RESULT = AtomicReferenceFieldUpdater.newUpdater<SafeContinuation<*>, Any?>(
|
||||
SafeContinuation::class.java, Any::class.java as Class<Any?>, "result")
|
||||
}
|
||||
|
||||
private class Fail(val exception: Throwable)
|
||||
|
||||
override fun resume(value: T) {
|
||||
while (true) { // lock-free loop
|
||||
val result = this.result // atomic read
|
||||
when {
|
||||
result === UNDECIDED -> if (RESULT.compareAndSet(this, UNDECIDED, value)) return
|
||||
result === COROUTINE_SUSPENDED -> if (RESULT.compareAndSet(this, COROUTINE_SUSPENDED, RESUMED)) {
|
||||
delegate.resume(value)
|
||||
return
|
||||
}
|
||||
else -> throw IllegalStateException("Already resumed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
while (true) { // lock-free loop
|
||||
val result = this.result // atomic read
|
||||
when {
|
||||
result === UNDECIDED -> if (RESULT.compareAndSet(this, UNDECIDED, Fail(exception))) return
|
||||
result === COROUTINE_SUSPENDED -> if (RESULT.compareAndSet(this, COROUTINE_SUSPENDED, RESUMED)) {
|
||||
delegate.resumeWithException(exception)
|
||||
return
|
||||
}
|
||||
else -> throw IllegalStateException("Already resumed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal fun getResult(): Any? {
|
||||
var result = this.result // atomic read
|
||||
if (result === UNDECIDED) {
|
||||
if (RESULT.compareAndSet(this, UNDECIDED, COROUTINE_SUSPENDED)) return COROUTINE_SUSPENDED
|
||||
result = this.result // reread volatile var
|
||||
}
|
||||
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,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.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmName("IntrinsicsKt")
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
package kotlin.coroutines.experimental.intrinsics
|
||||
import kotlin.coroutines.experimental.*
|
||||
|
||||
/**
|
||||
* Starts unintercepted coroutine without receiver and with result type [T] and executes it until its first suspension.
|
||||
* Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends.
|
||||
* In the later case, the [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
* This function is designed to be used from inside of [suspendCoroutineOrReturn] to resume the execution of suspended
|
||||
* coroutine using a reference to the suspending function.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <T> (suspend () -> T).startCoroutineUninterceptedOrReturn(
|
||||
completion: Continuation<T>
|
||||
): Any? = (this as Function1<Continuation<T>, Any?>).invoke(completion)
|
||||
|
||||
/**
|
||||
* Starts unintercepted coroutine with receiver type [R] and result type [T] and executes it until its first suspension.
|
||||
* Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends.
|
||||
* In the later case, the [completion] continuation is invoked when coroutine completes with result or exception.
|
||||
* This function is designed to be used from inside of [suspendCoroutineOrReturn] to resume the execution of suspended
|
||||
* coroutine using a reference to the suspending function.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <R, T> (suspend R.() -> T).startCoroutineUninterceptedOrReturn(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Any? = (this as Function2<R, Continuation<T>, Any?>).invoke(receiver, completion)
|
||||
|
||||
|
||||
// JVM declarations
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.jvm.JvmVersion
|
||||
public fun <T> (suspend () -> T).createCoroutineUnchecked(
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> =
|
||||
if (this !is kotlin.coroutines.experimental.jvm.internal.CoroutineImpl)
|
||||
buildContinuationByInvokeCall(completion) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
(this as Function1<Continuation<T>, Any?>).invoke(completion)
|
||||
}
|
||||
else
|
||||
(this.create(completion) as kotlin.coroutines.experimental.jvm.internal.CoroutineImpl).facade
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.jvm.JvmVersion
|
||||
public fun <R, T> (suspend R.() -> T).createCoroutineUnchecked(
|
||||
receiver: R,
|
||||
completion: Continuation<T>
|
||||
): Continuation<Unit> =
|
||||
if (this !is kotlin.coroutines.experimental.jvm.internal.CoroutineImpl)
|
||||
buildContinuationByInvokeCall(completion) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
(this as Function2<R, Continuation<T>, Any?>).invoke(receiver, completion)
|
||||
}
|
||||
else
|
||||
(this.create(receiver, completion) as kotlin.coroutines.experimental.jvm.internal.CoroutineImpl).facade
|
||||
|
||||
// INTERNAL DEFINITIONS
|
||||
|
||||
@kotlin.jvm.JvmVersion
|
||||
private inline fun <T> buildContinuationByInvokeCall(
|
||||
completion: Continuation<T>,
|
||||
crossinline block: () -> Any?
|
||||
): Continuation<Unit> {
|
||||
val continuation =
|
||||
object : Continuation<Unit> {
|
||||
override val context: CoroutineContext
|
||||
get() = completion.context
|
||||
|
||||
override fun resume(value: Unit) {
|
||||
processBareContinuationResume(completion, block)
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
completion.resumeWithException(exception)
|
||||
}
|
||||
}
|
||||
|
||||
return kotlin.coroutines.experimental.jvm.internal.interceptContinuationIfNeeded(completion.context, continuation)
|
||||
}
|
||||
@@ -1,73 +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.
|
||||
*/
|
||||
|
||||
@file:JvmVersion
|
||||
package kotlin.coroutines.experimental.jvm.internal
|
||||
|
||||
import java.lang.IllegalStateException
|
||||
import kotlin.coroutines.experimental.Continuation
|
||||
import kotlin.coroutines.experimental.CoroutineContext
|
||||
import kotlin.coroutines.experimental.processBareContinuationResume
|
||||
import kotlin.jvm.internal.Lambda
|
||||
|
||||
/**
|
||||
* @suppress
|
||||
*/
|
||||
abstract class CoroutineImpl(
|
||||
arity: Int,
|
||||
@JvmField
|
||||
protected var completion: Continuation<Any?>?
|
||||
) : Lambda(arity), Continuation<Any?> {
|
||||
|
||||
// label == -1 when coroutine cannot be started (it is just a factory object) or has already finished execution
|
||||
// label == 0 in initial part of the coroutine
|
||||
@JvmField
|
||||
protected var label: Int = if (completion != null) 0 else -1
|
||||
|
||||
private val _context: CoroutineContext? = completion?.context
|
||||
|
||||
override val context: CoroutineContext
|
||||
get() = _context!!
|
||||
|
||||
private var _facade: Continuation<Any?>? = null
|
||||
|
||||
val facade: Continuation<Any?> get() {
|
||||
if (_facade == null) _facade = interceptContinuationIfNeeded(_context!!, this)
|
||||
return _facade!!
|
||||
}
|
||||
|
||||
override fun resume(value: Any?) {
|
||||
processBareContinuationResume(completion!!) {
|
||||
doResume(value, null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun resumeWithException(exception: Throwable) {
|
||||
processBareContinuationResume(completion!!) {
|
||||
doResume(null, exception)
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun doResume(data: Any?, exception: Throwable?): Any?
|
||||
|
||||
open fun create(completion: Continuation<*>): Continuation<Unit> {
|
||||
throw IllegalStateException("create(Continuation) has not been overridden")
|
||||
}
|
||||
|
||||
open fun create(value: Any?, completion: Continuation<*>): Continuation<Unit> {
|
||||
throw IllegalStateException("create(Any?;Continuation) has not been overridden")
|
||||
}
|
||||
}
|
||||
-34
@@ -1,34 +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.
|
||||
*/
|
||||
|
||||
@file:JvmVersion
|
||||
@file:JvmName("CoroutineIntrinsics")
|
||||
package kotlin.coroutines.experimental.jvm.internal
|
||||
|
||||
import kotlin.coroutines.experimental.Continuation
|
||||
import kotlin.coroutines.experimental.ContinuationInterceptor
|
||||
import kotlin.coroutines.experimental.CoroutineContext
|
||||
|
||||
/**
|
||||
* @suppress
|
||||
*/
|
||||
fun <T> normalizeContinuation(continuation: Continuation<T>): Continuation<T> =
|
||||
(continuation as? CoroutineImpl)?.facade ?: continuation
|
||||
|
||||
internal fun <T> interceptContinuationIfNeeded(
|
||||
context: CoroutineContext,
|
||||
continuation: Continuation<T>
|
||||
) = context[ContinuationInterceptor]?.interceptContinuation(continuation) ?: continuation
|
||||
@@ -1,77 +0,0 @@
|
||||
@file:JvmVersion
|
||||
package kotlin.internal
|
||||
|
||||
import kotlin.*
|
||||
import java.util.regex.MatchResult
|
||||
|
||||
internal open class PlatformImplementations {
|
||||
|
||||
public open fun addSuppressed(cause: Throwable, exception: Throwable) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public open fun getMatchResultNamedGroup(matchResult: MatchResult, name: String): MatchGroup? {
|
||||
throw UnsupportedOperationException("Retrieving groups by name is not supported on this platform.")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@JvmField
|
||||
internal val IMPLEMENTATIONS: PlatformImplementations = run {
|
||||
val version = getJavaVersion()
|
||||
if (version >= 0x10008) {
|
||||
try {
|
||||
return@run Class.forName("kotlin.internal.jdk8.JDK8PlatformImplementations").newInstance() as PlatformImplementations
|
||||
}
|
||||
catch (e: ClassNotFoundException) { }
|
||||
try {
|
||||
return@run Class.forName("kotlin.internal.JRE8PlatformImplementations").newInstance() as PlatformImplementations
|
||||
}
|
||||
catch (e: ClassNotFoundException) { }
|
||||
}
|
||||
|
||||
if (version >= 0x10007) {
|
||||
try {
|
||||
return@run Class.forName("kotlin.internal.jdk7.JDK7PlatformImplementations").newInstance() as PlatformImplementations
|
||||
}
|
||||
catch (e: ClassNotFoundException) { }
|
||||
try {
|
||||
return@run Class.forName("kotlin.internal.JRE7PlatformImplementations").newInstance() as PlatformImplementations
|
||||
}
|
||||
catch (e: ClassNotFoundException) { }
|
||||
}
|
||||
|
||||
PlatformImplementations()
|
||||
}
|
||||
|
||||
private fun getJavaVersion(): Int {
|
||||
val default = 0x10006
|
||||
val version = System.getProperty("java.specification.version") ?: return default
|
||||
val firstDot = version.indexOf('.')
|
||||
if (firstDot < 0)
|
||||
return try { version.toInt() * 0x10000 } catch (e: NumberFormatException) { default }
|
||||
|
||||
var secondDot = version.indexOf('.', firstDot + 1)
|
||||
if (secondDot < 0) secondDot = version.length
|
||||
|
||||
val firstPart = version.substring(0, firstDot)
|
||||
val secondPart = version.substring(firstDot + 1, secondDot)
|
||||
return try {
|
||||
firstPart.toInt() * 0x10000 + secondPart.toInt()
|
||||
} catch (e: NumberFormatException) {
|
||||
default
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constant check of api version used during compilation
|
||||
*
|
||||
* This function is evaluated at compile time to a constant value,
|
||||
* so there should be no references to it in other modules.
|
||||
*
|
||||
* The function usages are validated to have literal argument values.
|
||||
*/
|
||||
@PublishedApi
|
||||
@SinceKotlin("1.2")
|
||||
internal fun apiVersionIsAtLeast(major: Int, minor: Int, patch: Int) =
|
||||
KotlinVersion.CURRENT.isAtLeast(major, minor, patch)
|
||||
@@ -1,72 +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.
|
||||
*/
|
||||
|
||||
@file:JvmName("CloseableKt")
|
||||
@file:JvmVersion
|
||||
package kotlin.io
|
||||
|
||||
import java.io.Closeable
|
||||
import kotlin.internal.*
|
||||
|
||||
/**
|
||||
* Executes the given [block] function on this resource and then closes it down correctly whether an exception
|
||||
* is thrown or not.
|
||||
*
|
||||
* @param block a function to process this [Closeable] resource.
|
||||
* @return the result of [block] function invoked on this resource.
|
||||
*/
|
||||
@InlineOnly
|
||||
@RequireKotlin("1.2", versionKind = RequireKotlinVersionKind.COMPILER_VERSION, message = "Requires newer compiler version to be inlined correctly.")
|
||||
public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {
|
||||
var exception: Throwable? = null
|
||||
try {
|
||||
return block(this)
|
||||
} catch (e: Throwable) {
|
||||
exception = e
|
||||
throw e
|
||||
} finally {
|
||||
when {
|
||||
apiVersionIsAtLeast(1, 1, 0) -> this.closeFinally(exception)
|
||||
this == null -> {}
|
||||
exception == null -> close()
|
||||
else ->
|
||||
try {
|
||||
close()
|
||||
} catch (closeException: Throwable) {
|
||||
// cause.addSuppressed(closeException) // ignored here
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes this [Closeable], suppressing possible exception or error thrown by [Closeable.close] function when
|
||||
* it's being closed due to some other [cause] exception occurred.
|
||||
*
|
||||
* The suppressed exception is added to the list of suppressed exceptions of [cause] exception, when it's supported.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@PublishedApi
|
||||
internal fun Closeable?.closeFinally(cause: Throwable?) = when {
|
||||
this == null -> {}
|
||||
cause == null -> close()
|
||||
else ->
|
||||
try {
|
||||
close()
|
||||
} catch (closeException: Throwable) {
|
||||
cause.addSuppressed(closeException)
|
||||
}
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
@file:JvmVersion
|
||||
@file:JvmName("ConsoleKt")
|
||||
|
||||
package kotlin.io
|
||||
|
||||
import kotlin.text.*
|
||||
import java.io.InputStream
|
||||
import java.nio.Buffer
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.CharBuffer
|
||||
import java.nio.charset.Charset
|
||||
import java.nio.charset.CharsetDecoder
|
||||
|
||||
/** Prints the given message to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun print(message: Any?) {
|
||||
System.out.print(message)
|
||||
}
|
||||
|
||||
/** Prints the given message to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun print(message: Int) {
|
||||
System.out.print(message)
|
||||
}
|
||||
|
||||
/** Prints the given message to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun print(message: Long) {
|
||||
System.out.print(message)
|
||||
}
|
||||
|
||||
/** Prints the given message to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun print(message: Byte) {
|
||||
System.out.print(message)
|
||||
}
|
||||
|
||||
/** Prints the given message to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun print(message: Short) {
|
||||
System.out.print(message)
|
||||
}
|
||||
|
||||
/** Prints the given message to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun print(message: Char) {
|
||||
System.out.print(message)
|
||||
}
|
||||
|
||||
/** Prints the given message to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun print(message: Boolean) {
|
||||
System.out.print(message)
|
||||
}
|
||||
|
||||
/** Prints the given message to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun print(message: Float) {
|
||||
System.out.print(message)
|
||||
}
|
||||
|
||||
/** Prints the given message to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun print(message: Double) {
|
||||
System.out.print(message)
|
||||
}
|
||||
|
||||
/** Prints the given message to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun print(message: CharArray) {
|
||||
System.out.print(message)
|
||||
}
|
||||
|
||||
/** Prints the given message and newline to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun println(message: Any?) {
|
||||
System.out.println(message)
|
||||
}
|
||||
|
||||
/** Prints the given message and newline to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun println(message: Int) {
|
||||
System.out.println(message)
|
||||
}
|
||||
|
||||
/** Prints the given message and newline to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun println(message: Long) {
|
||||
System.out.println(message)
|
||||
}
|
||||
|
||||
/** Prints the given message and newline to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun println(message: Byte) {
|
||||
System.out.println(message)
|
||||
}
|
||||
|
||||
/** Prints the given message and newline to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun println(message: Short) {
|
||||
System.out.println(message)
|
||||
}
|
||||
|
||||
/** Prints the given message and newline to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun println(message: Char) {
|
||||
System.out.println(message)
|
||||
}
|
||||
|
||||
/** Prints the given message and newline to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun println(message: Boolean) {
|
||||
System.out.println(message)
|
||||
}
|
||||
|
||||
/** Prints the given message and newline to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun println(message: Float) {
|
||||
System.out.println(message)
|
||||
}
|
||||
|
||||
/** Prints the given message and newline to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun println(message: Double) {
|
||||
System.out.println(message)
|
||||
}
|
||||
|
||||
/** Prints the given message and newline to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun println(message: CharArray) {
|
||||
System.out.println(message)
|
||||
}
|
||||
|
||||
/** Prints a newline to the standard output stream. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun println() {
|
||||
System.out.println()
|
||||
}
|
||||
|
||||
private const val BUFFER_SIZE: Int = 32
|
||||
private const val LINE_SEPARATOR_MAX_LENGTH: Int = 2
|
||||
|
||||
private val decoder: CharsetDecoder by lazy { Charset.defaultCharset().newDecoder() }
|
||||
|
||||
/**
|
||||
* Reads a line of input from the standard input stream.
|
||||
*
|
||||
* @return the line read or `null` if the input stream is redirected to a file and the end of file has been reached.
|
||||
*/
|
||||
fun readLine(): String? = readLine(System.`in`, decoder)
|
||||
|
||||
internal fun readLine(inputStream: InputStream, decoder: CharsetDecoder): String? {
|
||||
require(decoder.maxCharsPerByte() <= 1) { "Encodings with multiple chars per byte are not supported" }
|
||||
|
||||
val byteBuffer = ByteBuffer.allocate(BUFFER_SIZE)
|
||||
val charBuffer = CharBuffer.allocate(LINE_SEPARATOR_MAX_LENGTH)
|
||||
val stringBuilder = StringBuilder()
|
||||
|
||||
var read = inputStream.read()
|
||||
if (read == -1) return null
|
||||
do {
|
||||
byteBuffer.put(read.toByte())
|
||||
if (decoder.tryDecode(byteBuffer, charBuffer, false)) {
|
||||
if (charBuffer.containsLineSeparator()) {
|
||||
break
|
||||
}
|
||||
if (!charBuffer.hasRemaining()) {
|
||||
stringBuilder.append(charBuffer.dequeue())
|
||||
}
|
||||
}
|
||||
read = inputStream.read()
|
||||
} while (read != -1)
|
||||
|
||||
with(decoder) {
|
||||
tryDecode(byteBuffer, charBuffer, true) // throws exception if undecoded bytes are left
|
||||
reset()
|
||||
}
|
||||
|
||||
with(charBuffer) {
|
||||
val length = position()
|
||||
val first = get(0)
|
||||
val second = get(1)
|
||||
when (length) {
|
||||
2 -> {
|
||||
if (!(first == '\r' && second == '\n')) stringBuilder.append(first)
|
||||
if (second != '\n') stringBuilder.append(second)
|
||||
}
|
||||
1 -> if (first != '\n') stringBuilder.append(first)
|
||||
}
|
||||
}
|
||||
|
||||
return stringBuilder.toString()
|
||||
}
|
||||
|
||||
private fun CharsetDecoder.tryDecode(byteBuffer: ByteBuffer, charBuffer: CharBuffer, isEndOfStream: Boolean): Boolean {
|
||||
val positionBefore = charBuffer.position()
|
||||
byteBuffer.flip()
|
||||
with(decode(byteBuffer, charBuffer, isEndOfStream)) {
|
||||
if (isError) throwException()
|
||||
}
|
||||
return (charBuffer.position() > positionBefore).also { isDecoded ->
|
||||
if (isDecoded) byteBuffer.clear() else byteBuffer.flipBack()
|
||||
}
|
||||
}
|
||||
|
||||
private fun CharBuffer.containsLineSeparator(): Boolean {
|
||||
return get(1) == '\n' || get(0) == '\n'
|
||||
}
|
||||
|
||||
private fun Buffer.flipBack() {
|
||||
position(limit())
|
||||
limit(capacity())
|
||||
}
|
||||
|
||||
private fun CharBuffer.dequeue(): Char {
|
||||
flip()
|
||||
return get().also { compact() }
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
@file:JvmVersion
|
||||
@file:JvmName("ConstantsKt")
|
||||
package kotlin.io
|
||||
|
||||
/**
|
||||
* Returns the default buffer size when working with buffered streams.
|
||||
*/
|
||||
public const val DEFAULT_BUFFER_SIZE: Int = 8 * 1024
|
||||
|
||||
/**
|
||||
* Returns the default block size for forEachBlock().
|
||||
*/
|
||||
internal const val DEFAULT_BLOCK_SIZE: Int = 4096
|
||||
/**
|
||||
* Returns the minimum block size for forEachBlock().
|
||||
*/
|
||||
internal const val MINIMUM_BLOCK_SIZE: Int = 512
|
||||
@@ -1,50 +0,0 @@
|
||||
@file:JvmVersion
|
||||
package kotlin.io
|
||||
|
||||
import kotlin.text.*
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
private fun constructMessage(file: File, other: File?, reason: String?): String {
|
||||
val sb = StringBuilder(file.toString())
|
||||
if (other != null) {
|
||||
sb.append(" -> $other")
|
||||
}
|
||||
if (reason != null) {
|
||||
sb.append(": $reason")
|
||||
}
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* A base exception class for file system exceptions.
|
||||
* @property file the file on which the failed operation was performed.
|
||||
* @property other the second file involved in the operation, if any (for example, the target of a copy or move)
|
||||
* @property reason the description of the error
|
||||
*/
|
||||
open public class FileSystemException(public val file: File,
|
||||
public val other: File? = null,
|
||||
public val reason: String? = null
|
||||
) : IOException(constructMessage(file, other, reason))
|
||||
|
||||
/**
|
||||
* An exception class which is used when some file to create or copy to already exists.
|
||||
*/
|
||||
public class FileAlreadyExistsException(file: File,
|
||||
other: File? = null,
|
||||
reason: String? = null) : FileSystemException(file, other, reason)
|
||||
|
||||
/**
|
||||
* An exception class which is used when we have not enough access for some operation.
|
||||
*/
|
||||
public class AccessDeniedException(file: File,
|
||||
other: File? = null,
|
||||
reason: String? = null) : FileSystemException(file, other, reason)
|
||||
|
||||
/**
|
||||
* An exception class which is used when file to copy does not exist.
|
||||
*/
|
||||
public class NoSuchFileException(file: File,
|
||||
other: File? = null,
|
||||
reason: String? = null) : FileSystemException(file, other, reason)
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
@file:JvmVersion
|
||||
@file:JvmMultifileClass
|
||||
@file:JvmName("FilesKt")
|
||||
package kotlin.io
|
||||
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
import java.nio.charset.Charset
|
||||
import kotlin.internal.*
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new [FileReader] for reading the content of this file.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun File.reader(charset: Charset = Charsets.UTF_8): InputStreamReader = inputStream().reader(charset)
|
||||
|
||||
/**
|
||||
* Returns a new [BufferedReader] for reading the content of this file.
|
||||
*
|
||||
* @param bufferSize necessary size of the buffer.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun File.bufferedReader(charset: Charset = Charsets.UTF_8, bufferSize: Int = DEFAULT_BUFFER_SIZE): BufferedReader = reader(charset).buffered(bufferSize)
|
||||
|
||||
/**
|
||||
* Returns a new [FileWriter] for writing the content of this file.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun File.writer(charset: Charset = Charsets.UTF_8): OutputStreamWriter = outputStream().writer(charset)
|
||||
|
||||
/**
|
||||
* Returns a new [BufferedWriter] for writing the content of this file.
|
||||
*
|
||||
* @param bufferSize necessary size of the buffer.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun File.bufferedWriter(charset: Charset = Charsets.UTF_8, bufferSize: Int = DEFAULT_BUFFER_SIZE): BufferedWriter = writer(charset).buffered(bufferSize)
|
||||
|
||||
/**
|
||||
* Returns a new [PrintWriter] for writing the content of this file.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun File.printWriter(charset: Charset = Charsets.UTF_8): PrintWriter = PrintWriter(bufferedWriter(charset))
|
||||
|
||||
/**
|
||||
* Gets the entire content of this file as a byte array.
|
||||
*
|
||||
* This method is not recommended on huge files. It has an internal limitation of 2 GB byte array size.
|
||||
*
|
||||
* @return the entire content of this file as a byte array.
|
||||
*/
|
||||
public fun File.readBytes(): ByteArray = inputStream().use { input ->
|
||||
var offset = 0
|
||||
var remaining = this.length().also { length ->
|
||||
if (length > Int.MAX_VALUE) throw OutOfMemoryError("File $this is too big ($length bytes) to fit in memory.")
|
||||
}.toInt()
|
||||
val result = ByteArray(remaining)
|
||||
while (remaining > 0) {
|
||||
val read = input.read(result, offset, remaining)
|
||||
if (read < 0) break
|
||||
remaining -= read
|
||||
offset += read
|
||||
}
|
||||
if (remaining == 0) result else result.copyOf(offset)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content of this file as an [array] of bytes.
|
||||
* If this file already exists, it becomes overwritten.
|
||||
*
|
||||
* @param array byte array to write into this file.
|
||||
*/
|
||||
public fun File.writeBytes(array: ByteArray): Unit = FileOutputStream(this).use { it.write(array) }
|
||||
|
||||
/**
|
||||
* Appends an [array] of bytes to the content of this file.
|
||||
*
|
||||
* @param array byte array to append to this file.
|
||||
*/
|
||||
public fun File.appendBytes(array: ByteArray): Unit = FileOutputStream(this, true).use { it.write(array) }
|
||||
|
||||
/**
|
||||
* Gets the entire content of this file as a String using UTF-8 or specified [charset].
|
||||
*
|
||||
* This method is not recommended on huge files. It has an internal limitation of 2 GB file size.
|
||||
*
|
||||
* @param charset character set to use.
|
||||
* @return the entire content of this file as a String.
|
||||
*/
|
||||
public fun File.readText(charset: Charset = Charsets.UTF_8): String = readBytes().toString(charset)
|
||||
|
||||
/**
|
||||
* Sets the content of this file as [text] encoded using UTF-8 or specified [charset].
|
||||
* If this file exists, it becomes overwritten.
|
||||
*
|
||||
* @param text text to write into file.
|
||||
* @param charset character set to use.
|
||||
*/
|
||||
public fun File.writeText(text: String, charset: Charset = Charsets.UTF_8): Unit = writeBytes(text.toByteArray(charset))
|
||||
|
||||
/**
|
||||
* Appends [text] to the content of this file using UTF-8 or the specified [charset].
|
||||
*
|
||||
* @param text text to append to file.
|
||||
* @param charset character set to use.
|
||||
*/
|
||||
public fun File.appendText(text: String, charset: Charset = Charsets.UTF_8): Unit = appendBytes(text.toByteArray(charset))
|
||||
|
||||
/**
|
||||
* Reads file by byte blocks and calls [action] for each block read.
|
||||
* Block has default size which is implementation-dependent.
|
||||
* This functions passes the byte array and amount of bytes in the array to the [action] function.
|
||||
*
|
||||
* You can use this function for huge files.
|
||||
*
|
||||
* @param action function to process file blocks.
|
||||
*/
|
||||
public fun File.forEachBlock(action: (buffer: ByteArray, bytesRead: Int) -> Unit): Unit = forEachBlock(DEFAULT_BLOCK_SIZE, action)
|
||||
|
||||
/**
|
||||
* Reads file by byte blocks and calls [action] for each block read.
|
||||
* This functions passes the byte array and amount of bytes in the array to the [action] function.
|
||||
*
|
||||
* You can use this function for huge files.
|
||||
*
|
||||
* @param action function to process file blocks.
|
||||
* @param blockSize size of a block, replaced by 512 if it's less, 4096 by default.
|
||||
*/
|
||||
public fun File.forEachBlock(blockSize: Int, action: (buffer: ByteArray, bytesRead: Int) -> Unit): Unit {
|
||||
val arr = ByteArray(blockSize.coerceAtLeast(MINIMUM_BLOCK_SIZE))
|
||||
|
||||
inputStream().use { input ->
|
||||
do {
|
||||
val size = input.read(arr)
|
||||
if (size <= 0) {
|
||||
break
|
||||
} else {
|
||||
action(arr, size)
|
||||
}
|
||||
} while (true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads this file line by line using the specified [charset] and calls [action] for each line.
|
||||
* Default charset is UTF-8.
|
||||
*
|
||||
* You may use this function on huge files.
|
||||
*
|
||||
* @param charset character set to use.
|
||||
* @param action function to process file lines.
|
||||
*/
|
||||
public fun File.forEachLine(charset: Charset = Charsets.UTF_8, action: (line: String) -> Unit): Unit {
|
||||
// Note: close is called at forEachLine
|
||||
BufferedReader(InputStreamReader(FileInputStream(this), charset)).forEachLine(action)
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new FileInputStream of this file and returns it as a result.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun File.inputStream(): FileInputStream {
|
||||
return FileInputStream(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new FileOutputStream of this file and returns it as a result.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun File.outputStream(): FileOutputStream {
|
||||
return FileOutputStream(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the file content as a list of lines.
|
||||
*
|
||||
* Do not use this function for huge files.
|
||||
*
|
||||
* @param charset character set to use. By default uses UTF-8 charset.
|
||||
* @return list of file lines.
|
||||
*/
|
||||
public fun File.readLines(charset: Charset = Charsets.UTF_8): List<String> {
|
||||
val result = ArrayList<String>()
|
||||
forEachLine(charset) { result.add(it); }
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the [block] callback giving it a sequence of all the lines in this file and closes the reader once
|
||||
* the processing is complete.
|
||||
|
||||
* @param charset character set to use. By default uses UTF-8 charset.
|
||||
* @return the value returned by [block].
|
||||
*/
|
||||
@RequireKotlin("1.2", versionKind = RequireKotlinVersionKind.COMPILER_VERSION, message = "Requires newer compiler version to be inlined correctly.")
|
||||
public inline fun <T> File.useLines(charset: Charset = Charsets.UTF_8, block: (Sequence<String>) -> T): T =
|
||||
bufferedReader(charset).use { block(it.lineSequence()) }
|
||||
@@ -1,120 +0,0 @@
|
||||
@file:JvmVersion
|
||||
@file:JvmName("ByteStreamsKt")
|
||||
package kotlin.io
|
||||
|
||||
import java.io.*
|
||||
import java.nio.charset.Charset
|
||||
import java.util.NoSuchElementException
|
||||
|
||||
/** Returns an [Iterator] of bytes read from this input stream. */
|
||||
public operator fun BufferedInputStream.iterator(): ByteIterator =
|
||||
object : ByteIterator() {
|
||||
|
||||
var nextByte = -1
|
||||
|
||||
var nextPrepared = false
|
||||
|
||||
var finished = false
|
||||
|
||||
private fun prepareNext() {
|
||||
if (!nextPrepared && !finished) {
|
||||
nextByte = read()
|
||||
nextPrepared = true
|
||||
finished = (nextByte == -1)
|
||||
}
|
||||
}
|
||||
|
||||
public override fun hasNext(): Boolean {
|
||||
prepareNext()
|
||||
return !finished
|
||||
}
|
||||
|
||||
public override fun nextByte(): Byte {
|
||||
prepareNext()
|
||||
if (finished)
|
||||
throw NoSuchElementException("Input stream is over.")
|
||||
val res = nextByte.toByte()
|
||||
nextPrepared = false
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Creates a new byte input stream for the string. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.byteInputStream(charset: Charset = Charsets.UTF_8): ByteArrayInputStream = ByteArrayInputStream(toByteArray(charset))
|
||||
|
||||
/**
|
||||
* Creates an input stream for reading data from this byte array.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun ByteArray.inputStream(): ByteArrayInputStream = ByteArrayInputStream(this)
|
||||
|
||||
/**
|
||||
* Creates an input stream for reading data from the specified portion of this byte array.
|
||||
* @param offset the start offset of the portion of the array to read.
|
||||
* @param length the length of the portion of the array to read.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun ByteArray.inputStream(offset: Int, length: Int) : ByteArrayInputStream = ByteArrayInputStream(this, offset, length)
|
||||
|
||||
/**
|
||||
* Creates a buffered input stream wrapping this stream.
|
||||
* @param bufferSize the buffer size to use.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun InputStream.buffered(bufferSize: Int = DEFAULT_BUFFER_SIZE): BufferedInputStream
|
||||
= if (this is BufferedInputStream) this else BufferedInputStream(this, bufferSize)
|
||||
|
||||
/** Creates a reader on this input stream using UTF-8 or the specified [charset]. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun InputStream.reader(charset: Charset = Charsets.UTF_8): InputStreamReader = InputStreamReader(this, charset)
|
||||
|
||||
/** Creates a buffered reader on this input stream using UTF-8 or the specified [charset]. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun InputStream.bufferedReader(charset: Charset = Charsets.UTF_8): BufferedReader = reader(charset).buffered()
|
||||
|
||||
/**
|
||||
* Creates a buffered output stream wrapping this stream.
|
||||
* @param bufferSize the buffer size to use.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun OutputStream.buffered(bufferSize: Int = DEFAULT_BUFFER_SIZE): BufferedOutputStream
|
||||
= if (this is BufferedOutputStream) this else BufferedOutputStream(this, bufferSize)
|
||||
|
||||
/** Creates a writer on this output stream using UTF-8 or the specified [charset]. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun OutputStream.writer(charset: Charset = Charsets.UTF_8): OutputStreamWriter = OutputStreamWriter(this, charset)
|
||||
|
||||
/** Creates a buffered writer on this output stream using UTF-8 or the specified [charset]. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun OutputStream.bufferedWriter(charset: Charset = Charsets.UTF_8): BufferedWriter = writer(charset).buffered()
|
||||
|
||||
/**
|
||||
* Copies this stream to the given output stream, returning the number of bytes copied
|
||||
*
|
||||
* **Note** It is the caller's responsibility to close both of these resources.
|
||||
*/
|
||||
public fun InputStream.copyTo(out: OutputStream, bufferSize: Int = DEFAULT_BUFFER_SIZE): Long {
|
||||
var bytesCopied: Long = 0
|
||||
val buffer = ByteArray(bufferSize)
|
||||
var bytes = read(buffer)
|
||||
while (bytes >= 0) {
|
||||
out.write(buffer, 0, bytes)
|
||||
bytesCopied += bytes
|
||||
bytes = read(buffer)
|
||||
}
|
||||
return bytesCopied
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads this stream completely into a byte array.
|
||||
*
|
||||
* **Note**: It is the caller's responsibility to close this stream.
|
||||
*/
|
||||
public fun InputStream.readBytes(estimatedSize: Int = DEFAULT_BUFFER_SIZE): ByteArray {
|
||||
val buffer = ByteArrayOutputStream(Math.max(estimatedSize, this.available()))
|
||||
copyTo(buffer)
|
||||
return buffer.toByteArray()
|
||||
}
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
@file:JvmVersion
|
||||
@file:JvmName("TextStreamsKt")
|
||||
package kotlin.io
|
||||
|
||||
import java.io.*
|
||||
import java.nio.charset.Charset
|
||||
import java.net.URL
|
||||
import java.util.NoSuchElementException
|
||||
import kotlin.internal.*
|
||||
|
||||
|
||||
/** Returns a buffered reader wrapping this Reader, or this Reader itself if it is already buffered. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Reader.buffered(bufferSize: Int = DEFAULT_BUFFER_SIZE): BufferedReader
|
||||
= if (this is BufferedReader) this else BufferedReader(this, bufferSize)
|
||||
|
||||
/** Returns a buffered reader wrapping this Writer, or this Writer itself if it is already buffered. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Writer.buffered(bufferSize: Int = DEFAULT_BUFFER_SIZE): BufferedWriter
|
||||
= if (this is BufferedWriter) this else BufferedWriter(this, bufferSize)
|
||||
|
||||
/**
|
||||
* Iterates through each line of this reader, calls [action] for each line read
|
||||
* and closes the [Reader] when it's completed.
|
||||
*
|
||||
* @param action function to process file lines.
|
||||
*/
|
||||
public fun Reader.forEachLine(action: (String) -> Unit): Unit = useLines { it.forEach(action) }
|
||||
|
||||
/**
|
||||
* Reads this reader content as a list of lines.
|
||||
*
|
||||
* Do not use this function for huge files.
|
||||
*/
|
||||
public fun Reader.readLines(): List<String> {
|
||||
val result = arrayListOf<String>()
|
||||
forEachLine { result.add(it) }
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the [block] callback giving it a sequence of all the lines in this file and closes the reader once
|
||||
* the processing is complete.
|
||||
* @return the value returned by [block].
|
||||
*/
|
||||
@RequireKotlin("1.2", versionKind = RequireKotlinVersionKind.COMPILER_VERSION, message = "Requires newer compiler version to be inlined correctly.")
|
||||
public inline fun <T> Reader.useLines(block: (Sequence<String>) -> T): T =
|
||||
buffered().use { block(it.lineSequence()) }
|
||||
|
||||
/** Creates a new reader for the string. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.reader(): StringReader = StringReader(this)
|
||||
|
||||
/**
|
||||
* Returns a sequence of corresponding file lines.
|
||||
*
|
||||
* *Note*: the caller must close the underlying `BufferedReader`
|
||||
* when the iteration is finished; as the user may not complete the iteration loop (e.g. using a method like find() or any() on the iterator
|
||||
* may terminate the iteration early.
|
||||
*
|
||||
* We suggest you try the method [useLines] instead which closes the stream when the processing is complete.
|
||||
*
|
||||
* @return a sequence of corresponding file lines. The sequence returned can be iterated only once.
|
||||
*/
|
||||
public fun BufferedReader.lineSequence(): Sequence<String> = LinesSequence(this).constrainOnce()
|
||||
|
||||
private class LinesSequence(private val reader: BufferedReader) : Sequence<String> {
|
||||
override public fun iterator(): Iterator<String> {
|
||||
return object : Iterator<String> {
|
||||
private var nextValue: String? = null
|
||||
private var done = false
|
||||
|
||||
override public fun hasNext(): Boolean {
|
||||
if (nextValue == null && !done) {
|
||||
nextValue = reader.readLine()
|
||||
if (nextValue == null) done = true
|
||||
}
|
||||
return nextValue != null
|
||||
}
|
||||
|
||||
override public fun next(): String {
|
||||
if (!hasNext()) {
|
||||
throw NoSuchElementException()
|
||||
}
|
||||
val answer = nextValue
|
||||
nextValue = null
|
||||
return answer!!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads this reader completely as a String.
|
||||
*
|
||||
* *Note*: It is the caller's responsibility to close this reader.
|
||||
*
|
||||
* @return the string with corresponding file content.
|
||||
*/
|
||||
public fun Reader.readText(): String {
|
||||
val buffer = StringWriter()
|
||||
copyTo(buffer)
|
||||
return buffer.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies this reader to the given [out] writer, returning the number of characters copied.
|
||||
*
|
||||
* **Note** it is the caller's responsibility to close both of these resources.
|
||||
*
|
||||
* @param out writer to write to.
|
||||
* @param bufferSize size of character buffer to use in process.
|
||||
* @return number of characters copied.
|
||||
*/
|
||||
public fun Reader.copyTo(out: Writer, bufferSize: Int = DEFAULT_BUFFER_SIZE): Long {
|
||||
var charsCopied: Long = 0
|
||||
val buffer = CharArray(bufferSize)
|
||||
var chars = read(buffer)
|
||||
while (chars >= 0) {
|
||||
out.write(buffer, 0, chars)
|
||||
charsCopied += chars
|
||||
chars = read(buffer)
|
||||
}
|
||||
return charsCopied
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the entire content of this URL as a String using UTF-8 or the specified [charset].
|
||||
*
|
||||
* This method is not recommended on huge files.
|
||||
*
|
||||
* @param charset a character set to use.
|
||||
* @return a string with this URL entire content.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun URL.readText(charset: Charset = Charsets.UTF_8): String = readBytes().toString(charset)
|
||||
|
||||
/**
|
||||
* Reads the entire content of the URL as byte array.
|
||||
*
|
||||
* This method is not recommended on huge files.
|
||||
*
|
||||
* @return a byte array with this URL entire content.
|
||||
*/
|
||||
public fun URL.readBytes(): ByteArray = openStream().use { it.readBytes() }
|
||||
|
||||
@@ -1,20 +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.
|
||||
*/
|
||||
@file:JvmVersion
|
||||
package kotlin.io
|
||||
|
||||
// to use in shared code without imports
|
||||
internal typealias Serializable = java.io.Serializable
|
||||
@@ -1,143 +0,0 @@
|
||||
@file:JvmVersion
|
||||
@file:JvmMultifileClass
|
||||
@file:JvmName("FilesKt")
|
||||
package kotlin.io
|
||||
|
||||
import java.io.File
|
||||
import kotlin.*
|
||||
|
||||
/**
|
||||
* Estimation of a root name by a given file name.
|
||||
*
|
||||
* This implementation is able to find /, Drive:/, Drive: or
|
||||
* //network.name/root as possible root names.
|
||||
* / denotes File.separator here so \ can be used instead.
|
||||
* All other possible roots cannot be identified by this implementation.
|
||||
* It's also not guaranteed (but possible) that function will be able to detect a root
|
||||
* which is incorrect for current OS. For instance, in Unix function cannot detect
|
||||
* network root names like //network.name/root, but can detect Windows roots like C:/.
|
||||
*
|
||||
* @return length or a substring representing the root for this path, or zero if this file name is relative.
|
||||
*/
|
||||
private fun String.getRootLength(): Int {
|
||||
// Note: separators should be already replaced to system ones
|
||||
var first = indexOf(File.separatorChar, 0)
|
||||
if (first == 0) {
|
||||
if (length > 1 && this[1] == File.separatorChar) {
|
||||
// Network names like //my.host/home/something ? => //my.host/home/ should be root
|
||||
// NB: does not work in Unix because //my.host/home is converted into /my.host/home there
|
||||
// So in Windows we'll have root of //my.host/home but in Unix just /
|
||||
first = indexOf(File.separatorChar, 2)
|
||||
if (first >= 0) {
|
||||
first = indexOf(File.separatorChar, first + 1)
|
||||
if (first >= 0)
|
||||
return first + 1
|
||||
else
|
||||
return length
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
||||
// C:\
|
||||
if (first > 0 && this[first - 1] == ':') {
|
||||
first++
|
||||
return first
|
||||
}
|
||||
// C:
|
||||
if (first == -1 && endsWith(':'))
|
||||
return length
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimation of a root name for this file.
|
||||
*
|
||||
* This implementation is able to find /, Drive:/, Drive: or
|
||||
* //network.name/root as possible root names.
|
||||
* / denotes File.separator here so \ can be used instead.
|
||||
* All other possible roots cannot be identified by this implementation.
|
||||
* It's also not guaranteed (but possible) that function will be able to detect a root
|
||||
* which is incorrect for current OS. For instance, in Unix function cannot detect
|
||||
* network root names like //network.name/root, but can detect Windows roots like C:/.
|
||||
*
|
||||
* @return string representing the root for this file, or empty string is this file name is relative.
|
||||
*/
|
||||
internal val File.rootName: String
|
||||
get() = path.substring(0, path.getRootLength())
|
||||
|
||||
/**
|
||||
* Returns root component of this abstract name, like / from /home/user, or C:\ from C:\file.tmp,
|
||||
* or //my.host/home for //my.host/home/user
|
||||
*/
|
||||
internal val File.root: File
|
||||
get() = File(rootName)
|
||||
|
||||
/**
|
||||
* Determines whether this file has a root or it represents a relative path.
|
||||
*
|
||||
* Returns `true` when this file has non-empty root.
|
||||
*/
|
||||
public val File.isRooted: Boolean
|
||||
get() = path.getRootLength() > 0
|
||||
|
||||
/**
|
||||
* Represents the path to a file as a collection of directories.
|
||||
*
|
||||
* @property root the [File] object representing root of the path (for example, `/` or `C:` or empty for relative paths).
|
||||
* @property segments the list of [File] objects representing every directory in the path to the file,
|
||||
* up to an including the file itself.
|
||||
*/
|
||||
internal data class FilePathComponents
|
||||
internal constructor(public val root: File, public val segments: List<File>) {
|
||||
|
||||
/**
|
||||
* Returns a string representing the root for this file, or an empty string is this file name is relative.
|
||||
*/
|
||||
public val rootName: String get() = root.path
|
||||
|
||||
/**
|
||||
* Returns `true` when the [root] is not empty.
|
||||
*/
|
||||
public val isRooted: Boolean get() = root.path.isNotEmpty()
|
||||
|
||||
/**
|
||||
* Returns the number of elements in the path to the file.
|
||||
*/
|
||||
public val size: Int get() = segments.size
|
||||
|
||||
/**
|
||||
* Returns a sub-path of the path, starting with the directory at the specified [beginIndex] and up
|
||||
* to the specified [endIndex].
|
||||
*/
|
||||
public fun subPath(beginIndex: Int, endIndex: Int): File {
|
||||
if (beginIndex < 0 || beginIndex > endIndex || endIndex > size)
|
||||
throw IllegalArgumentException()
|
||||
|
||||
return File(segments.subList(beginIndex, endIndex).joinToString(File.separator))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the file into path components (the names of containing directories and the name of the file
|
||||
* itself) and returns the resulting collection of components.
|
||||
*/
|
||||
internal fun File.toComponents(): FilePathComponents {
|
||||
val path = path
|
||||
val rootLength = path.getRootLength()
|
||||
val rootName = path.substring(0, rootLength)
|
||||
val subPath = path.substring(rootLength)
|
||||
val list = if (subPath.isEmpty()) listOf() else subPath.split(File.separatorChar).map(::File)
|
||||
return FilePathComponents(File(rootName), list)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a relative pathname which is a subsequence of this pathname,
|
||||
* beginning from component [beginIndex], inclusive,
|
||||
* ending at component [endIndex], exclusive.
|
||||
* Number 0 belongs to a component closest to the root,
|
||||
* number count-1 belongs to a component farthest from the root.
|
||||
* @throws IllegalArgumentException if [beginIndex] is negative,
|
||||
* or [endIndex] is greater than existing number of components,
|
||||
* or [beginIndex] is greater than [endIndex].
|
||||
*/
|
||||
internal fun File.subPath(beginIndex: Int, endIndex: Int): File = toComponents().subPath(beginIndex, endIndex)
|
||||
@@ -1,276 +0,0 @@
|
||||
@file:JvmVersion
|
||||
@file:JvmMultifileClass
|
||||
@file:JvmName("FilesKt")
|
||||
package kotlin.io
|
||||
|
||||
import kotlin.*
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.Stack
|
||||
|
||||
/**
|
||||
* An enumeration to describe possible walk directions.
|
||||
* There are two of them: beginning from parents, ending with children,
|
||||
* and beginning from children, ending with parents. Both use depth-first search.
|
||||
*/
|
||||
public enum class FileWalkDirection {
|
||||
/** Depth-first search, directory is visited BEFORE its files */
|
||||
TOP_DOWN,
|
||||
/** Depth-first search, directory is visited AFTER its files */
|
||||
BOTTOM_UP
|
||||
// Do we want also breadth-first search?
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is intended to implement different file traversal methods.
|
||||
* It allows to iterate through all files inside a given directory.
|
||||
*
|
||||
* Use [File.walk], [File.walkTopDown] or [File.walkBottomUp] extension functions to instantiate a `FileTreeWalk` instance.
|
||||
|
||||
* If the file path given is just a file, walker iterates only it.
|
||||
* If the file path given does not exist, walker iterates nothing, i.e. it's equivalent to an empty sequence.
|
||||
*/
|
||||
public class FileTreeWalk private constructor(
|
||||
private val start: File,
|
||||
private val direction: FileWalkDirection = FileWalkDirection.TOP_DOWN,
|
||||
private val onEnter: ((File) -> Boolean)?,
|
||||
private val onLeave: ((File) -> Unit)?,
|
||||
private val onFail: ((f: File, e: IOException) -> Unit)?,
|
||||
private val maxDepth: Int = Int.MAX_VALUE
|
||||
) : Sequence<File> {
|
||||
|
||||
internal constructor(start: File, direction: FileWalkDirection = FileWalkDirection.TOP_DOWN): this(start, direction, null, null, null)
|
||||
|
||||
|
||||
/** Returns an iterator walking through files. */
|
||||
override public fun iterator(): Iterator<File> = FileTreeWalkIterator()
|
||||
|
||||
/** Abstract class that encapsulates file visiting in some order, beginning from a given [root] */
|
||||
private abstract class WalkState(val root: File) {
|
||||
/** Call of this function proceeds to a next file for visiting and returns it */
|
||||
abstract public fun step(): File?
|
||||
}
|
||||
|
||||
/** Abstract class that encapsulates directory visiting in some order, beginning from a given [rootDir] */
|
||||
private abstract class DirectoryState(rootDir: File): WalkState(rootDir) {
|
||||
init {
|
||||
if (_Assertions.ENABLED)
|
||||
assert(rootDir.isDirectory) { "rootDir must be verified to be directory beforehand." }
|
||||
}
|
||||
}
|
||||
|
||||
private inner class FileTreeWalkIterator : AbstractIterator<File>() {
|
||||
|
||||
// Stack of directory states, beginning from the start directory
|
||||
private val state = Stack<WalkState>()
|
||||
|
||||
init {
|
||||
if (start.isDirectory) {
|
||||
state.push(directoryState(start))
|
||||
} else if (start.isFile) {
|
||||
state.push(SingleFileState(start))
|
||||
} else {
|
||||
done()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun computeNext() {
|
||||
val nextFile = gotoNext()
|
||||
if (nextFile != null)
|
||||
setNext(nextFile)
|
||||
else
|
||||
done()
|
||||
}
|
||||
|
||||
|
||||
private fun directoryState(root: File): DirectoryState {
|
||||
return when (direction) {
|
||||
FileWalkDirection.TOP_DOWN -> TopDownDirectoryState(root)
|
||||
FileWalkDirection.BOTTOM_UP -> BottomUpDirectoryState(root)
|
||||
}
|
||||
}
|
||||
|
||||
tailrec private fun gotoNext(): File? {
|
||||
|
||||
if (state.empty()) {
|
||||
// There is nothing in the state
|
||||
return null
|
||||
}
|
||||
// Take next file from the top of the stack
|
||||
val topState = state.peek()!!
|
||||
val file = topState.step()
|
||||
if (file == null) {
|
||||
// There is nothing more on the top of the stack, go back
|
||||
state.pop()
|
||||
return gotoNext()
|
||||
} else {
|
||||
// Check that file/directory matches the filter
|
||||
if (file == topState.root || !file.isDirectory || state.size >= maxDepth) {
|
||||
// Proceed to a root directory or a simple file
|
||||
return file
|
||||
} else {
|
||||
// Proceed to a sub-directory
|
||||
state.push(directoryState(file))
|
||||
return gotoNext()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Visiting in bottom-up order */
|
||||
private inner class BottomUpDirectoryState(rootDir: File) : DirectoryState(rootDir) {
|
||||
|
||||
private var rootVisited = false
|
||||
|
||||
private var fileList: Array<File>? = null
|
||||
|
||||
private var fileIndex = 0
|
||||
|
||||
private var failed = false
|
||||
|
||||
/** First all children, then root directory */
|
||||
override public fun step(): File? {
|
||||
if (!failed && fileList == null) {
|
||||
if (onEnter?.invoke(root) == false) {
|
||||
return null
|
||||
}
|
||||
|
||||
fileList = root.listFiles()
|
||||
if (fileList == null) {
|
||||
onFail?.invoke(root, AccessDeniedException(file = root, reason = "Cannot list files in a directory"))
|
||||
failed = true
|
||||
}
|
||||
}
|
||||
if (fileList != null && fileIndex < fileList!!.size) {
|
||||
// First visit all files
|
||||
return fileList!![fileIndex++]
|
||||
} else if (!rootVisited) {
|
||||
// Then visit root
|
||||
rootVisited = true
|
||||
return root
|
||||
} else {
|
||||
// That's all
|
||||
onLeave?.invoke(root)
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Visiting in top-down order */
|
||||
private inner class TopDownDirectoryState(rootDir: File) : DirectoryState(rootDir) {
|
||||
|
||||
private var rootVisited = false
|
||||
|
||||
private var fileList: Array<File>? = null
|
||||
|
||||
private var fileIndex = 0
|
||||
|
||||
/** First root directory, then all children */
|
||||
override public fun step(): File? {
|
||||
if (!rootVisited) {
|
||||
// First visit root
|
||||
if (onEnter?.invoke(root) == false) {
|
||||
return null
|
||||
}
|
||||
|
||||
rootVisited = true
|
||||
return root
|
||||
} else if (fileList == null || fileIndex < fileList!!.size) {
|
||||
if (fileList == null) {
|
||||
// Then read an array of files, if any
|
||||
fileList = root.listFiles()
|
||||
if (fileList == null) {
|
||||
onFail?.invoke(root, AccessDeniedException(file = root, reason = "Cannot list files in a directory"))
|
||||
}
|
||||
if (fileList == null || fileList!!.size == 0) {
|
||||
onLeave?.invoke(root)
|
||||
return null
|
||||
}
|
||||
}
|
||||
// Then visit all files
|
||||
return fileList!![fileIndex++]
|
||||
} else {
|
||||
// That's all
|
||||
onLeave?.invoke(root)
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inner class SingleFileState(rootFile: File) : WalkState(rootFile) {
|
||||
private var visited: Boolean = false
|
||||
|
||||
init {
|
||||
if (_Assertions.ENABLED)
|
||||
assert(rootFile.isFile) { "rootFile must be verified to be file beforehand." }
|
||||
}
|
||||
|
||||
override fun step(): File? {
|
||||
if (visited) return null
|
||||
visited = true
|
||||
return root
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a predicate [function], that is called on any entered directory before its files are visited
|
||||
* and before it is visited itself.
|
||||
*
|
||||
* If the [function] returns `false` the directory is not entered and neither it nor its files are visited.
|
||||
*/
|
||||
public fun onEnter(function: (File) -> Boolean): FileTreeWalk {
|
||||
return FileTreeWalk(start, direction, onEnter = function, onLeave = onLeave, onFail = onFail, maxDepth = maxDepth)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a callback [function], that is called on any left directory after its files are visited and after it is visited itself.
|
||||
*/
|
||||
public fun onLeave(function: (File) -> Unit): FileTreeWalk {
|
||||
return FileTreeWalk(start, direction, onEnter = onEnter, onLeave = function, onFail = onFail, maxDepth = maxDepth)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a callback [function], that is called on a directory when it's impossible to get its file list.
|
||||
*
|
||||
* [onEnter] and [onLeave] callback functions are called even in this case.
|
||||
*/
|
||||
public fun onFail(function: (File, IOException) -> Unit): FileTreeWalk {
|
||||
return FileTreeWalk(start, direction, onEnter = onEnter, onLeave = onLeave, onFail = function, maxDepth = maxDepth)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum [depth] of a directory tree to traverse. By default there is no limit.
|
||||
*
|
||||
* The value must be positive and [Int.MAX_VALUE] is used to specify an unlimited depth.
|
||||
*
|
||||
* With a value of 1, walker visits only the origin directory and all its immediate children,
|
||||
* with a value of 2 also grandchildren, etc.
|
||||
*/
|
||||
public fun maxDepth(depth: Int): FileTreeWalk {
|
||||
if (depth <= 0)
|
||||
throw IllegalArgumentException("depth must be positive, but was $depth.")
|
||||
return FileTreeWalk(start, direction, onEnter, onLeave, onFail, depth)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a sequence for visiting this directory and all its content.
|
||||
*
|
||||
* @param direction walk direction, top-down (by default) or bottom-up.
|
||||
*/
|
||||
public fun File.walk(direction: FileWalkDirection = FileWalkDirection.TOP_DOWN): FileTreeWalk =
|
||||
FileTreeWalk(this, direction)
|
||||
|
||||
/**
|
||||
* Gets a sequence for visiting this directory and all its content in top-down order.
|
||||
* Depth-first search is used and directories are visited before all their files.
|
||||
*/
|
||||
public fun File.walkTopDown(): FileTreeWalk = walk(FileWalkDirection.TOP_DOWN)
|
||||
|
||||
/**
|
||||
* Gets a sequence for visiting this directory and all its content in bottom-up order.
|
||||
* Depth-first search is used and directories are visited after all their files.
|
||||
*/
|
||||
public fun File.walkBottomUp(): FileTreeWalk = walk(FileWalkDirection.BOTTOM_UP)
|
||||
@@ -1,437 +0,0 @@
|
||||
@file:JvmVersion
|
||||
@file:JvmMultifileClass
|
||||
@file:JvmName("FilesKt")
|
||||
package kotlin.io
|
||||
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
import kotlin.*
|
||||
import kotlin.text.*
|
||||
import kotlin.comparisons.*
|
||||
|
||||
/**
|
||||
* Creates an empty directory in the specified [directory], using the given [prefix] and [suffix] to generate its name.
|
||||
*
|
||||
* If [prefix] is not specified then some unspecified name will be used.
|
||||
* If [suffix] is not specified then ".tmp" will be used.
|
||||
* If [directory] is not specified then the default temporary-file directory will be used.
|
||||
*
|
||||
* @return a file object corresponding to a newly-created directory.
|
||||
*
|
||||
* @throws IOException in case of input/output error.
|
||||
* @throws IllegalArgumentException if [prefix] is shorter than three symbols.
|
||||
*/
|
||||
public fun createTempDir(prefix: String = "tmp", suffix: String? = null, directory: File? = null): File {
|
||||
val dir = File.createTempFile(prefix, suffix, directory)
|
||||
dir.delete()
|
||||
if (dir.mkdir()) {
|
||||
return dir
|
||||
} else {
|
||||
throw IOException("Unable to create temporary directory $dir.")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new empty file in the specified [directory], using the given [prefix] and [suffix] to generate its name.
|
||||
*
|
||||
* If [prefix] is not specified then some unspecified name will be used.
|
||||
* If [suffix] is not specified then ".tmp" will be used.
|
||||
* If [directory] is not specified then the default temporary-file directory will be used.
|
||||
*
|
||||
* @return a file object corresponding to a newly-created file.
|
||||
*
|
||||
* @throws IOException in case of input/output error.
|
||||
* @throws IllegalArgumentException if [prefix] is shorter than three symbols.
|
||||
*/
|
||||
public fun createTempFile(prefix: String = "tmp", suffix: String? = null, directory: File? = null): File {
|
||||
return File.createTempFile(prefix, suffix, directory)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extension of this file (not including the dot), or an empty string if it doesn't have one.
|
||||
*/
|
||||
public val File.extension: String
|
||||
get() = name.substringAfterLast('.', "")
|
||||
|
||||
/**
|
||||
* Returns [path][File.path] of this File using the invariant separator '/' to
|
||||
* separate the names in the name sequence.
|
||||
*/
|
||||
public val File.invariantSeparatorsPath: String
|
||||
get() = if (File.separatorChar != '/') path.replace(File.separatorChar, '/') else path
|
||||
|
||||
/**
|
||||
* Returns file's name without an extension.
|
||||
*/
|
||||
public val File.nameWithoutExtension: String
|
||||
get() = name.substringBeforeLast(".")
|
||||
|
||||
/**
|
||||
* Calculates the relative path for this file from [base] file.
|
||||
* Note that the [base] file is treated as a directory.
|
||||
* If this file matches the [base] file, then an empty string will be returned.
|
||||
*
|
||||
* @return relative path from [base] to this.
|
||||
*
|
||||
* @throws IllegalArgumentException if this and base paths have different roots.
|
||||
*/
|
||||
public fun File.toRelativeString(base: File): String
|
||||
= toRelativeStringOrNull(base) ?: throw IllegalArgumentException("this and base files have different roots: $this and $base.")
|
||||
|
||||
/**
|
||||
* Calculates the relative path for this file from [base] file.
|
||||
* Note that the [base] file is treated as a directory.
|
||||
* If this file matches the [base] file, then a [File] with empty path will be returned.
|
||||
*
|
||||
* @return File with relative path from [base] to this.
|
||||
*
|
||||
* @throws IllegalArgumentException if this and base paths have different roots.
|
||||
*/
|
||||
public fun File.relativeTo(base: File): File = File(this.toRelativeString(base))
|
||||
|
||||
/**
|
||||
* Calculates the relative path for this file from [base] file.
|
||||
* Note that the [base] file is treated as a directory.
|
||||
* If this file matches the [base] file, then a [File] with empty path will be returned.
|
||||
*
|
||||
* @return File with relative path from [base] to this, or `this` if this and base paths have different roots.
|
||||
*/
|
||||
public fun File.relativeToOrSelf(base: File): File
|
||||
= toRelativeStringOrNull(base)?.let(::File) ?: this
|
||||
|
||||
/**
|
||||
* Calculates the relative path for this file from [base] file.
|
||||
* Note that the [base] file is treated as a directory.
|
||||
* If this file matches the [base] file, then a [File] with empty path will be returned.
|
||||
*
|
||||
* @return File with relative path from [base] to this, or `null` if this and base paths have different roots.
|
||||
*/
|
||||
public fun File.relativeToOrNull(base: File): File?
|
||||
= toRelativeStringOrNull(base)?.let(::File)
|
||||
|
||||
|
||||
private fun File.toRelativeStringOrNull(base: File): String? {
|
||||
// Check roots
|
||||
val thisComponents = this.toComponents().normalize()
|
||||
val baseComponents = base.toComponents().normalize()
|
||||
if (thisComponents.root != baseComponents.root) {
|
||||
return null
|
||||
}
|
||||
|
||||
val baseCount = baseComponents.size
|
||||
val thisCount = thisComponents.size
|
||||
|
||||
val sameCount = run countSame@ {
|
||||
var i = 0
|
||||
val maxSameCount = minOf(thisCount, baseCount)
|
||||
while (i < maxSameCount && thisComponents.segments[i] == baseComponents.segments[i])
|
||||
i++
|
||||
return@countSame i
|
||||
}
|
||||
|
||||
// Annihilate differing base components by adding required number of .. parts
|
||||
val res = StringBuilder()
|
||||
for (i in baseCount - 1 downTo sameCount) {
|
||||
if (baseComponents.segments[i].name == "..") {
|
||||
return null
|
||||
}
|
||||
|
||||
res.append("..")
|
||||
|
||||
if (i != sameCount) {
|
||||
res.append(File.separatorChar)
|
||||
}
|
||||
}
|
||||
|
||||
// Add remaining this components
|
||||
if (sameCount < thisCount) {
|
||||
// If some .. were appended
|
||||
if (sameCount < baseCount)
|
||||
res.append(File.separatorChar)
|
||||
|
||||
thisComponents.segments.drop(sameCount).joinTo(res, File.separator)
|
||||
}
|
||||
|
||||
return res.toString()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copies this file to the given [target] file.
|
||||
*
|
||||
* If some directories on a way to the [target] are missing, then they will be created.
|
||||
* If the [target] file already exists, this function will fail unless [overwrite] argument is set to `true`.
|
||||
*
|
||||
* When [overwrite] is `true` and [target] is a directory, it is replaced only if it is empty.
|
||||
*
|
||||
* If this file is a directory, it is copied without its content, i.e. an empty [target] directory is created.
|
||||
* If you want to copy directory including its contents, use [copyRecursively].
|
||||
*
|
||||
* The operation doesn't preserve copied file attributes such as creation/modification date, permissions, etc.
|
||||
*
|
||||
* @param overwrite `true` if destination overwrite is allowed.
|
||||
* @param bufferSize the buffer size to use when copying.
|
||||
* @return the [target] file.
|
||||
* @throws NoSuchFileException if the source file doesn't exist.
|
||||
* @throws FileAlreadyExistsException if the destination file already exists and [overwrite] argument is set to `false`.
|
||||
* @throws IOException if any errors occur while copying.
|
||||
*/
|
||||
public fun File.copyTo(target: File, overwrite: Boolean = false, bufferSize: Int = DEFAULT_BUFFER_SIZE): File {
|
||||
if (!this.exists()) {
|
||||
throw NoSuchFileException(file = this, reason = "The source file doesn't exist.")
|
||||
}
|
||||
|
||||
if (target.exists()) {
|
||||
val stillExists = if (!overwrite) true else !target.delete()
|
||||
|
||||
if (stillExists) {
|
||||
throw FileAlreadyExistsException(file = this,
|
||||
other = target,
|
||||
reason = "The destination file already exists.")
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isDirectory) {
|
||||
if (!target.mkdirs())
|
||||
throw FileSystemException(file = this, other = target, reason = "Failed to create target directory.")
|
||||
} else {
|
||||
target.parentFile?.mkdirs()
|
||||
|
||||
this.inputStream().use { input ->
|
||||
target.outputStream().use { output ->
|
||||
input.copyTo(output, bufferSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum that can be used to specify behaviour of the `copyRecursively()` function
|
||||
* in exceptional conditions.
|
||||
*/
|
||||
public enum class OnErrorAction {
|
||||
/** Skip this file and go to the next. */
|
||||
SKIP,
|
||||
|
||||
/** Terminate the evaluation of the function. */
|
||||
TERMINATE
|
||||
}
|
||||
|
||||
/** Private exception class, used to terminate recursive copying. */
|
||||
private class TerminateException(file: File) : FileSystemException(file) {}
|
||||
|
||||
/**
|
||||
* Copies this file with all its children to the specified destination [target] path.
|
||||
* If some directories on the way to the destination are missing, then they will be created.
|
||||
*
|
||||
* If this file path points to a single file, then it will be copied to a file with the path [target].
|
||||
* If this file path points to a directory, then its children will be copied to a directory with the path [target].
|
||||
*
|
||||
* If the [target] already exists, it will be deleted before copying when the [overwrite] parameter permits so.
|
||||
*
|
||||
* The operation doesn't preserve copied file attributes such as creation/modification date, permissions, etc.
|
||||
*
|
||||
* If any errors occur during the copying, then further actions will depend on the result of the call
|
||||
* to `onError(File, IOException)` function, that will be called with arguments,
|
||||
* specifying the file that caused the error and the exception itself.
|
||||
* By default this function rethrows exceptions.
|
||||
*
|
||||
* Exceptions that can be passed to the `onError` function:
|
||||
*
|
||||
* - [NoSuchFileException] - if there was an attempt to copy a non-existent file
|
||||
* - [FileAlreadyExistsException] - if there is a conflict
|
||||
* - [AccessDeniedException] - if there was an attempt to open a directory that didn't succeed.
|
||||
* - [IOException] - if some problems occur when copying.
|
||||
*
|
||||
* Note that if this function fails, then partial copying may have taken place.
|
||||
*
|
||||
* @param overwrite `true` if it is allowed to overwrite existing destination files and directories.
|
||||
* @return `false` if the copying was terminated, `true` otherwise.
|
||||
*/
|
||||
public fun File.copyRecursively(target: File,
|
||||
overwrite: Boolean = false,
|
||||
onError: (File, IOException) -> OnErrorAction =
|
||||
{ _, exception -> throw exception }
|
||||
): Boolean {
|
||||
if (!exists()) {
|
||||
return onError(this, NoSuchFileException(file = this, reason = "The source file doesn't exist.")) !=
|
||||
OnErrorAction.TERMINATE
|
||||
}
|
||||
try {
|
||||
// We cannot break for loop from inside a lambda, so we have to use an exception here
|
||||
for (src in walkTopDown().onFail { f, e -> if (onError(f, e) == OnErrorAction.TERMINATE) throw TerminateException(f) }) {
|
||||
if (!src.exists()) {
|
||||
if (onError(src, NoSuchFileException(file = src, reason = "The source file doesn't exist.")) ==
|
||||
OnErrorAction.TERMINATE)
|
||||
return false
|
||||
} else {
|
||||
val relPath = src.toRelativeString(this)
|
||||
val dstFile = File(target, relPath)
|
||||
if (dstFile.exists() && !(src.isDirectory && dstFile.isDirectory)) {
|
||||
val stillExists = if (!overwrite) true else {
|
||||
if (dstFile.isDirectory)
|
||||
!dstFile.deleteRecursively()
|
||||
else
|
||||
!dstFile.delete()
|
||||
}
|
||||
|
||||
if (stillExists) {
|
||||
if (onError(dstFile, FileAlreadyExistsException(file = src,
|
||||
other = dstFile,
|
||||
reason = "The destination file already exists.")) == OnErrorAction.TERMINATE)
|
||||
return false
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if (src.isDirectory) {
|
||||
dstFile.mkdirs()
|
||||
} else {
|
||||
if (src.copyTo(dstFile, overwrite).length() != src.length()) {
|
||||
if (onError(src, IOException("Source file wasn't copied completely, length of destination file differs.")) == OnErrorAction.TERMINATE)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
} catch (e: TerminateException) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete this file with all its children.
|
||||
* Note that if this operation fails then partial deletion may have taken place.
|
||||
*
|
||||
* @return `true` if the file or directory is successfully deleted, `false` otherwise.
|
||||
*/
|
||||
public fun File.deleteRecursively(): Boolean = walkBottomUp().fold(true, { res, it -> (it.delete() || !it.exists()) && res })
|
||||
|
||||
/**
|
||||
* Determines whether this file belongs to the same root as [other]
|
||||
* and starts with all components of [other] in the same order.
|
||||
* So if [other] has N components, first N components of `this` must be the same as in [other].
|
||||
*
|
||||
* @return `true` if this path starts with [other] path, `false` otherwise.
|
||||
*/
|
||||
public fun File.startsWith(other: File): Boolean {
|
||||
val components = toComponents()
|
||||
val otherComponents = other.toComponents()
|
||||
if (components.root != otherComponents.root)
|
||||
return false
|
||||
return if (components.size < otherComponents.size) false
|
||||
else components.segments.subList(0, otherComponents.size).equals(otherComponents.segments)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this file belongs to the same root as [other]
|
||||
* and starts with all components of [other] in the same order.
|
||||
* So if [other] has N components, first N components of `this` must be the same as in [other].
|
||||
*
|
||||
* @return `true` if this path starts with [other] path, `false` otherwise.
|
||||
*/
|
||||
public fun File.startsWith(other: String): Boolean = startsWith(File(other))
|
||||
|
||||
/**
|
||||
* Determines whether this file path ends with the path of [other] file.
|
||||
*
|
||||
* If [other] is rooted path it must be equal to this.
|
||||
* If [other] is relative path then last N components of `this` must be the same as all components in [other],
|
||||
* where N is the number of components in [other].
|
||||
*
|
||||
* @return `true` if this path ends with [other] path, `false` otherwise.
|
||||
*/
|
||||
public fun File.endsWith(other: File): Boolean {
|
||||
val components = toComponents()
|
||||
val otherComponents = other.toComponents()
|
||||
if (otherComponents.isRooted)
|
||||
return this == other
|
||||
val shift = components.size - otherComponents.size
|
||||
return if (shift < 0) false
|
||||
else components.segments.subList(shift, components.size).equals(otherComponents.segments)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this file belongs to the same root as [other]
|
||||
* and ends with all components of [other] in the same order.
|
||||
* So if [other] has N components, last N components of `this` must be the same as in [other].
|
||||
* For relative [other], `this` can belong to any root.
|
||||
*
|
||||
* @return `true` if this path ends with [other] path, `false` otherwise.
|
||||
*/
|
||||
public fun File.endsWith(other: String): Boolean = endsWith(File(other))
|
||||
|
||||
/**
|
||||
* Removes all . and resolves all possible .. in this file name.
|
||||
* For instance, `File("/foo/./bar/gav/../baaz").normalize()` is `File("/foo/bar/baaz")`.
|
||||
*
|
||||
* @return normalized pathname with . and possibly .. removed.
|
||||
*/
|
||||
public fun File.normalize(): File
|
||||
= with (toComponents()) { root.resolve(segments.normalize().joinToString(File.separator)) }
|
||||
|
||||
private fun FilePathComponents.normalize(): FilePathComponents
|
||||
= FilePathComponents(root, segments.normalize())
|
||||
|
||||
private fun List<File>.normalize(): List<File> {
|
||||
val list: MutableList<File> = ArrayList(this.size)
|
||||
for (file in this) {
|
||||
when (file.name) {
|
||||
"." -> {}
|
||||
".." -> if (!list.isEmpty() && list.last().name != "..") list.removeAt(list.size - 1) else list.add(file)
|
||||
else -> list.add(file)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds [relative] file to this, considering this as a directory.
|
||||
* If [relative] has a root, [relative] is returned back.
|
||||
* For instance, `File("/foo/bar").resolve(File("gav"))` is `File("/foo/bar/gav")`.
|
||||
* This function is complementary with [relativeTo],
|
||||
* so `f.resolve(g.relativeTo(f)) == g` should be always `true` except for different roots case.
|
||||
*
|
||||
* @return concatenated this and [relative] paths, or just [relative] if it's absolute.
|
||||
*/
|
||||
public fun File.resolve(relative: File): File {
|
||||
if (relative.isRooted)
|
||||
return relative
|
||||
val baseName = this.toString()
|
||||
return if (baseName.isEmpty() || baseName.endsWith(File.separatorChar)) File(baseName + relative) else File(baseName + File.separatorChar + relative)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds [relative] name to this, considering this as a directory.
|
||||
* If [relative] has a root, [relative] is returned back.
|
||||
* For instance, `File("/foo/bar").resolve("gav")` is `File("/foo/bar/gav")`.
|
||||
*
|
||||
* @return concatenated this and [relative] paths, or just [relative] if it's absolute.
|
||||
*/
|
||||
public fun File.resolve(relative: String): File = resolve(File(relative))
|
||||
|
||||
/**
|
||||
* Adds [relative] file to this parent directory.
|
||||
* If [relative] has a root or this has no parent directory, [relative] is returned back.
|
||||
* For instance, `File("/foo/bar").resolveSibling(File("gav"))` is `File("/foo/gav")`.
|
||||
*
|
||||
* @return concatenated this.parent and [relative] paths, or just [relative] if it's absolute or this has no parent.
|
||||
*/
|
||||
public fun File.resolveSibling(relative: File): File {
|
||||
val components = this.toComponents()
|
||||
val parentSubPath = if (components.size == 0) File("..") else components.subPath(0, components.size - 1)
|
||||
return components.root.resolve(parentSubPath).resolve(relative)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds [relative] name to this parent directory.
|
||||
* If [relative] has a root or this has no parent directory, [relative] is returned back.
|
||||
* For instance, `File("/foo/bar").resolveSibling("gav")` is `File("/foo/gav")`.
|
||||
*
|
||||
* @return concatenated this.parent and [relative] paths, or just [relative] if it's absolute or this has no parent.
|
||||
*/
|
||||
public fun File.resolveSibling(relative: String): File = resolveSibling(File(relative))
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
@file:JvmVersion
|
||||
|
||||
package kotlin.jvm
|
||||
|
||||
import kotlin.internal.RequireKotlin
|
||||
import kotlin.internal.RequireKotlinVersionKind
|
||||
|
||||
/**
|
||||
* Specifies that a JVM default method should be generated for non-abstract Kotlin interface member.
|
||||
*
|
||||
* This annotation requires explicit compilation flag to be enabled: `-Xenable-jvm-default`.
|
||||
* Also this requires jvmTarget 1.8 or higher.
|
||||
* Adding or removing this annotation to an interface member is a binary incompatible change.
|
||||
* @JvmDefault methods are excluded from interface delegation.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@RequireKotlin("1.2.40", versionKind = RequireKotlinVersionKind.COMPILER_VERSION)
|
||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
|
||||
annotation class JvmDefault
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.
|
||||
*/
|
||||
@file:JvmVersion
|
||||
package kotlin.jvm
|
||||
|
||||
@Target(AnnotationTarget.FILE, AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
internal annotation class JvmVersion(public val minimum: Int = 6, public val maximum: Int = 100)
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.
|
||||
*/
|
||||
|
||||
@file:JvmVersion
|
||||
package kotlin.jvm.internal.unsafe
|
||||
|
||||
import kotlin.*
|
||||
|
||||
private fun monitorEnter(@Suppress("UNUSED_PARAMETER") monitor: Any): Unit = throw UnsupportedOperationException("This function can only be used privately")
|
||||
|
||||
private fun monitorExit(@Suppress("UNUSED_PARAMETER") monitor: Any): Unit = throw UnsupportedOperationException("This function can only be used privately")
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("RangesKt")
|
||||
package kotlin.ranges
|
||||
|
||||
import kotlin.*
|
||||
|
||||
/**
|
||||
* A closed range of values of type `Float`.
|
||||
*
|
||||
* Numbers are compared with the ends of this range according to IEEE-754.
|
||||
*/
|
||||
@JvmVersion
|
||||
private class ClosedFloatRange (
|
||||
start: Float,
|
||||
endInclusive: Float
|
||||
): ClosedFloatingPointRange<Float> {
|
||||
private val _start = start
|
||||
private val _endInclusive = endInclusive
|
||||
override val start: Float get() = _start
|
||||
override val endInclusive: Float get() = _endInclusive
|
||||
|
||||
override fun lessThanOrEquals(a: Float, b: Float): Boolean = a <= b
|
||||
|
||||
override fun contains(value: Float): Boolean = value >= _start && value <= _endInclusive
|
||||
override fun isEmpty(): Boolean = !(_start <= _endInclusive)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is ClosedFloatRange && (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"
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a range from this [Float] value to the specified [that] value.
|
||||
*
|
||||
* Numbers are compared with the ends of this range according to IEEE-754.
|
||||
* @sample samples.ranges.Ranges.rangeFromFloat
|
||||
*/
|
||||
@JvmVersion
|
||||
@SinceKotlin("1.1")
|
||||
public operator fun Float.rangeTo(that: Float): ClosedFloatingPointRange<Float> = ClosedFloatRange(this, that)
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
@file:kotlin.jvm.JvmName("ProcessKt")
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
package kotlin.system
|
||||
|
||||
import kotlin.*
|
||||
|
||||
/**
|
||||
* Terminates the currently running Java Virtual Machine. The
|
||||
* argument serves as a status code; by convention, a nonzero status
|
||||
* code indicates abnormal termination.
|
||||
*
|
||||
* This method never returns normally.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun exitProcess(status: Int): Nothing {
|
||||
System.exit(status)
|
||||
throw RuntimeException("System.exit returned normally, while it was supposed to halt JVM.")
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
@file:kotlin.jvm.JvmName("TimingKt")
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
package kotlin.system
|
||||
|
||||
/**
|
||||
* Executes the given block and returns elapsed time in milliseconds.
|
||||
*/
|
||||
public inline fun measureTimeMillis(block: () -> Unit) : Long {
|
||||
val start = System.currentTimeMillis()
|
||||
block()
|
||||
return System.currentTimeMillis() - start
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given block and returns elapsed time in nanoseconds.
|
||||
*/
|
||||
public inline fun measureNanoTime(block: () -> Unit) : Long {
|
||||
val start = System.nanoTime()
|
||||
block()
|
||||
return System.nanoTime() - start
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
@file:JvmVersion
|
||||
package kotlin.text
|
||||
|
||||
import kotlin.*
|
||||
|
||||
/**
|
||||
* Represents the character general category in the Unicode specification.
|
||||
*/
|
||||
public enum class CharCategory(public val value: Int, public val code: String) {
|
||||
/**
|
||||
* General category "Cn" in the Unicode specification.
|
||||
*/
|
||||
UNASSIGNED(Character.UNASSIGNED.toInt(), "Cn"),
|
||||
|
||||
/**
|
||||
* General category "Lu" in the Unicode specification.
|
||||
*/
|
||||
UPPERCASE_LETTER(Character.UPPERCASE_LETTER.toInt(), "Lu"),
|
||||
|
||||
/**
|
||||
* General category "Ll" in the Unicode specification.
|
||||
*/
|
||||
LOWERCASE_LETTER(Character.LOWERCASE_LETTER.toInt(), "Ll"),
|
||||
|
||||
/**
|
||||
* General category "Lt" in the Unicode specification.
|
||||
*/
|
||||
TITLECASE_LETTER(Character.TITLECASE_LETTER.toInt(), "Lt"),
|
||||
|
||||
/**
|
||||
* General category "Lm" in the Unicode specification.
|
||||
*/
|
||||
MODIFIER_LETTER(Character.MODIFIER_LETTER.toInt(), "Lm"),
|
||||
|
||||
/**
|
||||
* General category "Lo" in the Unicode specification.
|
||||
*/
|
||||
OTHER_LETTER(Character.OTHER_LETTER.toInt(), "Lo"),
|
||||
|
||||
/**
|
||||
* General category "Mn" in the Unicode specification.
|
||||
*/
|
||||
NON_SPACING_MARK(Character.NON_SPACING_MARK.toInt(), "Mn"),
|
||||
|
||||
/**
|
||||
* General category "Me" in the Unicode specification.
|
||||
*/
|
||||
ENCLOSING_MARK(Character.ENCLOSING_MARK.toInt(), "Me"),
|
||||
|
||||
/**
|
||||
* General category "Mc" in the Unicode specification.
|
||||
*/
|
||||
COMBINING_SPACING_MARK(Character.COMBINING_SPACING_MARK.toInt(), "Mc"),
|
||||
|
||||
/**
|
||||
* General category "Nd" in the Unicode specification.
|
||||
*/
|
||||
DECIMAL_DIGIT_NUMBER(Character.DECIMAL_DIGIT_NUMBER.toInt(), "Nd"),
|
||||
|
||||
/**
|
||||
* General category "Nl" in the Unicode specification.
|
||||
*/
|
||||
LETTER_NUMBER(Character.LETTER_NUMBER.toInt(), "Nl"),
|
||||
|
||||
/**
|
||||
* General category "No" in the Unicode specification.
|
||||
*/
|
||||
OTHER_NUMBER(Character.OTHER_NUMBER.toInt(), "No"),
|
||||
|
||||
/**
|
||||
* General category "Zs" in the Unicode specification.
|
||||
*/
|
||||
SPACE_SEPARATOR(Character.SPACE_SEPARATOR.toInt(), "Zs"),
|
||||
|
||||
/**
|
||||
* General category "Zl" in the Unicode specification.
|
||||
*/
|
||||
LINE_SEPARATOR(Character.LINE_SEPARATOR.toInt(), "Zl"),
|
||||
|
||||
/**
|
||||
* General category "Zp" in the Unicode specification.
|
||||
*/
|
||||
PARAGRAPH_SEPARATOR(Character.PARAGRAPH_SEPARATOR.toInt(), "Zp"),
|
||||
|
||||
/**
|
||||
* General category "Cc" in the Unicode specification.
|
||||
*/
|
||||
CONTROL(Character.CONTROL.toInt(), "Cc"),
|
||||
|
||||
/**
|
||||
* General category "Cf" in the Unicode specification.
|
||||
*/
|
||||
FORMAT(Character.FORMAT.toInt(), "Cf"),
|
||||
|
||||
/**
|
||||
* General category "Co" in the Unicode specification.
|
||||
*/
|
||||
PRIVATE_USE(Character.PRIVATE_USE.toInt(), "Co"),
|
||||
|
||||
/**
|
||||
* General category "Cs" in the Unicode specification.
|
||||
*/
|
||||
SURROGATE(Character.SURROGATE.toInt(), "Cs"),
|
||||
|
||||
/**
|
||||
* General category "Pd" in the Unicode specification.
|
||||
*/
|
||||
DASH_PUNCTUATION(Character.DASH_PUNCTUATION.toInt(), "Pd"),
|
||||
|
||||
/**
|
||||
* General category "Ps" in the Unicode specification.
|
||||
*/
|
||||
START_PUNCTUATION(Character.START_PUNCTUATION.toInt(), "Ps"),
|
||||
|
||||
/**
|
||||
* General category "Pe" in the Unicode specification.
|
||||
*/
|
||||
END_PUNCTUATION(Character.END_PUNCTUATION.toInt(), "Pe"),
|
||||
|
||||
/**
|
||||
* General category "Pc" in the Unicode specification.
|
||||
*/
|
||||
CONNECTOR_PUNCTUATION(Character.CONNECTOR_PUNCTUATION.toInt(), "Pc"),
|
||||
|
||||
/**
|
||||
* General category "Po" in the Unicode specification.
|
||||
*/
|
||||
OTHER_PUNCTUATION(Character.OTHER_PUNCTUATION.toInt(), "Po"),
|
||||
|
||||
/**
|
||||
* General category "Sm" in the Unicode specification.
|
||||
*/
|
||||
MATH_SYMBOL(Character.MATH_SYMBOL.toInt(), "Sm"),
|
||||
|
||||
/**
|
||||
* General category "Sc" in the Unicode specification.
|
||||
*/
|
||||
CURRENCY_SYMBOL(Character.CURRENCY_SYMBOL.toInt(), "Sc"),
|
||||
|
||||
/**
|
||||
* General category "Sk" in the Unicode specification.
|
||||
*/
|
||||
MODIFIER_SYMBOL(Character.MODIFIER_SYMBOL.toInt(), "Sk"),
|
||||
|
||||
/**
|
||||
* General category "So" in the Unicode specification.
|
||||
*/
|
||||
OTHER_SYMBOL(Character.OTHER_SYMBOL.toInt(), "So"),
|
||||
|
||||
/**
|
||||
* General category "Pi" in the Unicode specification.
|
||||
*/
|
||||
INITIAL_QUOTE_PUNCTUATION(Character.INITIAL_QUOTE_PUNCTUATION.toInt(), "Pi"),
|
||||
|
||||
/**
|
||||
* General category "Pf" in the Unicode specification.
|
||||
*/
|
||||
FINAL_QUOTE_PUNCTUATION(Character.FINAL_QUOTE_PUNCTUATION.toInt(), "Pf");
|
||||
|
||||
/**
|
||||
* Returns `true` if [char] character belongs to this category.
|
||||
*/
|
||||
public operator fun contains(char: Char): Boolean = Character.getType(char) == this.value
|
||||
|
||||
|
||||
public companion object {
|
||||
private val categoryMap by lazy { CharCategory.values().associateBy { it.value } }
|
||||
|
||||
public fun valueOf(category: Int): CharCategory = categoryMap[category] ?: throw IllegalArgumentException("Category #$category is not defined.")
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
@file:JvmVersion
|
||||
package kotlin.text
|
||||
|
||||
import kotlin.*
|
||||
|
||||
/**
|
||||
* Represents the Unicode directionality of a character.
|
||||
* Character directionality is used to calculate the
|
||||
* visual ordering of text.
|
||||
*/
|
||||
public enum class CharDirectionality(public val value: Int) {
|
||||
|
||||
/**
|
||||
* Undefined bidirectional character type. Undefined `char`
|
||||
* values have undefined directionality in the Unicode specification.
|
||||
*/
|
||||
UNDEFINED(Character.DIRECTIONALITY_UNDEFINED.toInt()),
|
||||
|
||||
/**
|
||||
* Strong bidirectional character type "L" in the Unicode specification.
|
||||
*/
|
||||
LEFT_TO_RIGHT(Character.DIRECTIONALITY_LEFT_TO_RIGHT.toInt()),
|
||||
|
||||
/**
|
||||
* Strong bidirectional character type "R" in the Unicode specification.
|
||||
*/
|
||||
RIGHT_TO_LEFT(Character.DIRECTIONALITY_RIGHT_TO_LEFT.toInt()),
|
||||
|
||||
/**
|
||||
* Strong bidirectional character type "AL" in the Unicode specification.
|
||||
*/
|
||||
RIGHT_TO_LEFT_ARABIC(Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC.toInt()),
|
||||
|
||||
/**
|
||||
* Weak bidirectional character type "EN" in the Unicode specification.
|
||||
*/
|
||||
EUROPEAN_NUMBER(Character.DIRECTIONALITY_EUROPEAN_NUMBER.toInt()),
|
||||
|
||||
/**
|
||||
* Weak bidirectional character type "ES" in the Unicode specification.
|
||||
*/
|
||||
EUROPEAN_NUMBER_SEPARATOR(Character.DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR.toInt()),
|
||||
|
||||
/**
|
||||
* Weak bidirectional character type "ET" in the Unicode specification.
|
||||
*/
|
||||
EUROPEAN_NUMBER_TERMINATOR(Character.DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR.toInt()),
|
||||
|
||||
/**
|
||||
* Weak bidirectional character type "AN" in the Unicode specification.
|
||||
*/
|
||||
ARABIC_NUMBER(Character.DIRECTIONALITY_ARABIC_NUMBER.toInt()),
|
||||
|
||||
/**
|
||||
* Weak bidirectional character type "CS" in the Unicode specification.
|
||||
*/
|
||||
COMMON_NUMBER_SEPARATOR(Character.DIRECTIONALITY_COMMON_NUMBER_SEPARATOR.toInt()),
|
||||
|
||||
/**
|
||||
* Weak bidirectional character type "NSM" in the Unicode specification.
|
||||
*/
|
||||
NONSPACING_MARK(Character.DIRECTIONALITY_NONSPACING_MARK.toInt()),
|
||||
|
||||
/**
|
||||
* Weak bidirectional character type "BN" in the Unicode specification.
|
||||
*/
|
||||
BOUNDARY_NEUTRAL(Character.DIRECTIONALITY_BOUNDARY_NEUTRAL.toInt()),
|
||||
|
||||
/**
|
||||
* Neutral bidirectional character type "B" in the Unicode specification.
|
||||
*/
|
||||
PARAGRAPH_SEPARATOR(Character.DIRECTIONALITY_PARAGRAPH_SEPARATOR.toInt()),
|
||||
|
||||
/**
|
||||
* Neutral bidirectional character type "S" in the Unicode specification.
|
||||
*/
|
||||
SEGMENT_SEPARATOR(Character.DIRECTIONALITY_SEGMENT_SEPARATOR.toInt()),
|
||||
|
||||
/**
|
||||
* Neutral bidirectional character type "WS" in the Unicode specification.
|
||||
*/
|
||||
WHITESPACE(Character.DIRECTIONALITY_WHITESPACE.toInt()),
|
||||
|
||||
/**
|
||||
* Neutral bidirectional character type "ON" in the Unicode specification.
|
||||
*/
|
||||
OTHER_NEUTRALS(Character.DIRECTIONALITY_OTHER_NEUTRALS.toInt()),
|
||||
|
||||
/**
|
||||
* Strong bidirectional character type "LRE" in the Unicode specification.
|
||||
*/
|
||||
LEFT_TO_RIGHT_EMBEDDING(Character.DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING.toInt()),
|
||||
|
||||
/**
|
||||
* Strong bidirectional character type "LRO" in the Unicode specification.
|
||||
*/
|
||||
LEFT_TO_RIGHT_OVERRIDE(Character.DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE.toInt()),
|
||||
|
||||
/**
|
||||
* Strong bidirectional character type "RLE" in the Unicode specification.
|
||||
*/
|
||||
RIGHT_TO_LEFT_EMBEDDING(Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING.toInt()),
|
||||
|
||||
/**
|
||||
* Strong bidirectional character type "RLO" in the Unicode specification.
|
||||
*/
|
||||
RIGHT_TO_LEFT_OVERRIDE(Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE.toInt()),
|
||||
|
||||
/**
|
||||
* Weak bidirectional character type "PDF" in the Unicode specification.
|
||||
*/
|
||||
POP_DIRECTIONAL_FORMAT(Character.DIRECTIONALITY_POP_DIRECTIONAL_FORMAT.toInt());
|
||||
|
||||
|
||||
public companion object {
|
||||
private val directionalityMap by lazy { CharDirectionality.values().associateBy { it.value } }
|
||||
|
||||
public fun valueOf(directionality: Int): CharDirectionality = directionalityMap[directionality] ?: throw IllegalArgumentException("Directionality #$directionality is not defined.")
|
||||
}
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.
|
||||
*/
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("CharsKt")
|
||||
|
||||
|
||||
package kotlin.text
|
||||
|
||||
import kotlin.*
|
||||
|
||||
/**
|
||||
* Returns `true` if this character (Unicode code point) is defined in Unicode.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.isDefined(): Boolean = Character.isDefined(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if this character is a letter.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.isLetter(): Boolean = Character.isLetter(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if this character is a letter or digit.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.isLetterOrDigit(): Boolean = Character.isLetterOrDigit(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if this character (Unicode code point) is a digit.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.isDigit(): Boolean = Character.isDigit(this)
|
||||
|
||||
|
||||
/**
|
||||
* Returns `true` if this character (Unicode code point) should be regarded as an ignorable
|
||||
* character in a Java identifier or a Unicode identifier.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.isIdentifierIgnorable(): Boolean = Character.isIdentifierIgnorable(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if this character is an ISO control character.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.isISOControl(): Boolean = Character.isISOControl(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if this character (Unicode code point) may be part of a Java identifier as other than the first character.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.isJavaIdentifierPart(): Boolean = Character.isJavaIdentifierPart(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if this character is permissible as the first character in a Java identifier.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.isJavaIdentifierStart(): Boolean = Character.isJavaIdentifierStart(this)
|
||||
|
||||
/**
|
||||
* Determines whether a character is whitespace according to the Unicode standard.
|
||||
* Returns `true` if the character is whitespace.
|
||||
*/
|
||||
public fun Char.isWhitespace(): Boolean = Character.isWhitespace(this) || Character.isSpaceChar(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if this character is upper case.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.isUpperCase(): Boolean = Character.isUpperCase(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if this character is lower case.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.isLowerCase(): Boolean = Character.isLowerCase(this)
|
||||
|
||||
/**
|
||||
* Converts this character to uppercase.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.toUpperCase(): Char = Character.toUpperCase(this)
|
||||
|
||||
/**
|
||||
* Converts this character to lowercase.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.toLowerCase(): Char = Character.toLowerCase(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if this character is a titlecase character.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.isTitleCase(): Boolean = Character.isTitleCase(this)
|
||||
|
||||
/**
|
||||
* Converts this character to titlecase.
|
||||
*
|
||||
* @see Character.toTitleCase
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.toTitleCase(): Char = Character.toTitleCase(this)
|
||||
|
||||
/**
|
||||
* Returns a value indicating a character's general category.
|
||||
*/
|
||||
public val Char.category: CharCategory get() = CharCategory.valueOf(Character.getType(this))
|
||||
|
||||
/**
|
||||
* Returns the Unicode directionality property for the given character.
|
||||
*/
|
||||
public val Char.directionality: CharDirectionality get() = CharDirectionality.valueOf(Character.getDirectionality(this).toInt())
|
||||
|
||||
/**
|
||||
* Returns `true` if this character is a Unicode high-surrogate code unit (also known as leading-surrogate code unit).
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.isHighSurrogate(): Boolean = Character.isHighSurrogate(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if this character is a Unicode low-surrogate code unit (also known as trailing-surrogate code unit).
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Char.isLowSurrogate(): Boolean = Character.isLowSurrogate(this)
|
||||
|
||||
// TODO Provide name for JVM7+
|
||||
///**
|
||||
// * Returns the Unicode name of this character, or `null` if the code point of this character is unassigned.
|
||||
// */
|
||||
//public fun Char.name(): String? = Character.getName(this.toInt())
|
||||
|
||||
|
||||
|
||||
internal fun digitOf(char: Char, radix: Int): Int = Character.digit(char.toInt(), radix)
|
||||
|
||||
/**
|
||||
* Checks whether the given [radix] is valid radix for string to number and number to string conversion.
|
||||
*/
|
||||
@PublishedApi
|
||||
internal fun checkRadix(radix: Int): Int {
|
||||
if(radix !in Character.MIN_RADIX..Character.MAX_RADIX) {
|
||||
throw IllegalArgumentException("radix $radix was not in valid range ${Character.MIN_RADIX..Character.MAX_RADIX}")
|
||||
}
|
||||
return radix
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
@file:JvmName("CharsetsKt")
|
||||
@file:JvmVersion
|
||||
package kotlin.text
|
||||
|
||||
import java.nio.charset.*
|
||||
|
||||
/**
|
||||
* Returns a named charset with the given [charsetName] name.
|
||||
*
|
||||
* @throws UnsupportedCharsetException If the specified named charset is not available.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun charset(charsetName: String): Charset = Charset.forName(charsetName)
|
||||
|
||||
/**
|
||||
* Constant definitions for the standard [charsets](Charset). These
|
||||
* charsets are guaranteed to be available on every implementation of the Java
|
||||
* platform.
|
||||
*/
|
||||
public object Charsets {
|
||||
/**
|
||||
* Eight-bit UCS Transformation Format.
|
||||
*/
|
||||
@JvmField
|
||||
public val UTF_8: Charset = Charset.forName("UTF-8")
|
||||
|
||||
/**
|
||||
* Sixteen-bit UCS Transformation Format, byte order identified by an
|
||||
* optional byte-order mark.
|
||||
*/
|
||||
@JvmField
|
||||
public val UTF_16: Charset = Charset.forName("UTF-16")
|
||||
|
||||
/**
|
||||
* Sixteen-bit UCS Transformation Format, big-endian byte order.
|
||||
*/
|
||||
@JvmField
|
||||
public val UTF_16BE: Charset = Charset.forName("UTF-16BE")
|
||||
|
||||
/**
|
||||
* Sixteen-bit UCS Transformation Format, little-endian byte order.
|
||||
*/
|
||||
@JvmField
|
||||
public val UTF_16LE: Charset = Charset.forName("UTF-16LE")
|
||||
|
||||
/**
|
||||
* Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the
|
||||
* Unicode character set.
|
||||
*/
|
||||
@JvmField
|
||||
public val US_ASCII: Charset = Charset.forName("US-ASCII")
|
||||
|
||||
/**
|
||||
* ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.
|
||||
*/
|
||||
@JvmField
|
||||
public val ISO_8859_1: Charset = Charset.forName("ISO-8859-1")
|
||||
|
||||
/**
|
||||
* 32-bit Unicode (or UCS) Transformation Format, byte order identified by an optional byte-order mark
|
||||
*/
|
||||
public val UTF_32: Charset
|
||||
@JvmName("UTF32")
|
||||
get() = utf_32 ?: run {
|
||||
val charset: Charset = Charset.forName("UTF-32")
|
||||
utf_32 = charset
|
||||
charset
|
||||
}
|
||||
private var utf_32: Charset? = null
|
||||
|
||||
/**
|
||||
* 32-bit Unicode (or UCS) Transformation Format, little-endian byte order.
|
||||
*/
|
||||
public val UTF_32LE: Charset
|
||||
@JvmName("UTF32_LE")
|
||||
get() = utf_32le ?: run {
|
||||
val charset: Charset = Charset.forName("UTF-32LE")
|
||||
utf_32le = charset
|
||||
charset
|
||||
}
|
||||
private var utf_32le: Charset? = null
|
||||
|
||||
/**
|
||||
* 32-bit Unicode (or UCS) Transformation Format, big-endian byte order.
|
||||
*/
|
||||
public val UTF_32BE: Charset
|
||||
@JvmName("UTF32_BE")
|
||||
get() = utf_32be ?: run {
|
||||
val charset: Charset = Charset.forName("UTF-32BE")
|
||||
utf_32be = charset
|
||||
charset
|
||||
}
|
||||
private var utf_32be: Charset? = null
|
||||
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("StringsKt")
|
||||
|
||||
package kotlin.text
|
||||
|
||||
/**
|
||||
* Sets the character at the specified [index] to the specified [value].
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun StringBuilder.set(index: Int, value: Char): Unit = this.setCharAt(index, value)
|
||||
|
||||
|
||||
private object SystemProperties {
|
||||
/** Line separator for current system. */
|
||||
@JvmField
|
||||
val LINE_SEPARATOR = System.getProperty("line.separator")!!
|
||||
}
|
||||
|
||||
/** Appends a line separator to this Appendable. */
|
||||
public fun Appendable.appendln(): Appendable = append(SystemProperties.LINE_SEPARATOR)
|
||||
|
||||
/** Appends value to the given Appendable and line separator after it. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Appendable.appendln(value: CharSequence?): Appendable = append(value).appendln()
|
||||
|
||||
/** Appends value to the given Appendable and line separator after it. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Appendable.appendln(value: Char): Appendable = append(value).appendln()
|
||||
|
||||
/** Appends a line separator to this StringBuilder. */
|
||||
public fun StringBuilder.appendln(): StringBuilder = append(SystemProperties.LINE_SEPARATOR)
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: StringBuffer?): StringBuilder = append(value).appendln()
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: CharSequence?): StringBuilder = append(value).appendln()
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: String?): StringBuilder = append(value).appendln()
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: Any?): StringBuilder = append(value).appendln()
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: StringBuilder?): StringBuilder = append(value).appendln()
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: CharArray): StringBuilder = append(value).appendln()
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: Char): StringBuilder = append(value).appendln()
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: Boolean): StringBuilder = append(value).appendln()
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: Int): StringBuilder = append(value).appendln()
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: Short): StringBuilder = append(value.toInt()).appendln()
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: Byte): StringBuilder = append(value.toInt()).appendln()
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: Long): StringBuilder = append(value).appendln()
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: Float): StringBuilder = append(value).appendln()
|
||||
|
||||
/** Appends [value] to this [StringBuilder], followed by a line separator. */
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun StringBuilder.appendln(value: Double): StringBuilder = append(value).appendln()
|
||||
@@ -1,300 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("StringsKt")
|
||||
@file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
|
||||
|
||||
package kotlin.text
|
||||
|
||||
import kotlin.*
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string representation of this [Byte] value in the specified [radix].
|
||||
*
|
||||
* @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Byte.toString(radix: Int): String = this.toInt().toString(checkRadix(radix))
|
||||
|
||||
/**
|
||||
* Returns a string representation of this [Short] value in the specified [radix].
|
||||
*
|
||||
* @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Short.toString(radix: Int): String = this.toInt().toString(checkRadix(radix))
|
||||
|
||||
/**
|
||||
* Returns a string representation of this [Int] value in the specified [radix].
|
||||
*
|
||||
* @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Int.toString(radix: Int): String = java.lang.Integer.toString(this, checkRadix(radix))
|
||||
|
||||
/**
|
||||
* Returns a string representation of this [Long] value in the specified [radix].
|
||||
*
|
||||
* @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Long.toString(radix: Int): String = java.lang.Long.toString(this, checkRadix(radix))
|
||||
|
||||
/**
|
||||
* Returns `true` if the contents of this string is equal to the word "true", ignoring case, and `false` otherwise.
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toBoolean(): Boolean = java.lang.Boolean.parseBoolean(this)
|
||||
|
||||
/**
|
||||
* 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.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toByte(): Byte = java.lang.Byte.parseByte(this)
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toByte(radix: Int): Byte = java.lang.Byte.parseByte(this, checkRadix(radix))
|
||||
|
||||
|
||||
/**
|
||||
* 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.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toShort(): Short = java.lang.Short.parseShort(this)
|
||||
|
||||
/**
|
||||
* Parses the string as a [Short] number and returns the result.
|
||||
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toShort(radix: Int): Short = java.lang.Short.parseShort(this, checkRadix(radix))
|
||||
|
||||
/**
|
||||
* 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.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toInt(): Int = java.lang.Integer.parseInt(this)
|
||||
|
||||
/**
|
||||
* Parses the string as an [Int] number and returns the result.
|
||||
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toInt(radix: Int): Int = java.lang.Integer.parseInt(this, checkRadix(radix))
|
||||
|
||||
/**
|
||||
* 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.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toLong(): Long = java.lang.Long.parseLong(this)
|
||||
|
||||
/**
|
||||
* Parses the string as a [Long] number and returns the result.
|
||||
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toLong(radix: Int): Long = java.lang.Long.parseLong(this, checkRadix(radix))
|
||||
|
||||
/**
|
||||
* Parses the string as a [Float] number and returns the result.
|
||||
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toFloat(): Float = java.lang.Float.parseFloat(this)
|
||||
|
||||
/**
|
||||
* Parses the string as a [Double] number and returns the result.
|
||||
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toDouble(): Double = java.lang.Double.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")
|
||||
@kotlin.jvm.JvmVersion
|
||||
public fun String.toFloatOrNull(): Float? = screenFloatValue(this, java.lang.Float::parseFloat)
|
||||
|
||||
/**
|
||||
* Parses the string as a [Double] number and returns the result
|
||||
* or `null` if the string is not a valid representation of a number.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.jvm.JvmVersion
|
||||
public fun String.toDoubleOrNull(): Double? = screenFloatValue(this, java.lang.Double::parseDouble)
|
||||
|
||||
/**
|
||||
* Parses the string as a [java.math.BigInteger] number and returns the result.
|
||||
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toBigInteger(): java.math.BigInteger =
|
||||
java.math.BigInteger(this)
|
||||
|
||||
/**
|
||||
* Parses the string as a [java.math.BigInteger] number and returns the result.
|
||||
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toBigInteger(radix: Int): java.math.BigInteger =
|
||||
java.math.BigInteger(this, checkRadix(radix))
|
||||
|
||||
/**
|
||||
* Parses the string as a [java.math.BigInteger] number and returns the result
|
||||
* or `null` if the string is not a valid representation of a number.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.jvm.JvmVersion
|
||||
public fun String.toBigIntegerOrNull(): java.math.BigInteger? = toBigIntegerOrNull(10)
|
||||
|
||||
/**
|
||||
* Parses the string as a [java.math.BigInteger] number and returns the result
|
||||
* or `null` if the string is not a valid representation of a number.
|
||||
*
|
||||
* @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.jvm.JvmVersion
|
||||
public fun String.toBigIntegerOrNull(radix: Int): java.math.BigInteger? {
|
||||
checkRadix(radix)
|
||||
val length = this.length
|
||||
when (length) {
|
||||
0 -> return null
|
||||
1 -> if (digitOf(this[0], radix) < 0) return null
|
||||
else -> {
|
||||
val start = if (this[0] == '-') 1 else 0
|
||||
for (index in start until length) {
|
||||
if (digitOf(this[index], radix) < 0)
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
return toBigInteger(radix)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses the string as a [java.math.BigDecimal] number and returns the result.
|
||||
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toBigDecimal(): java.math.BigDecimal =
|
||||
java.math.BigDecimal(this)
|
||||
|
||||
/**
|
||||
* Parses the string as a [java.math.BigDecimal] number and returns the result.
|
||||
* @throws NumberFormatException if the string is not a valid representation of a number.
|
||||
*
|
||||
* @param mathContext specifies the precision and the rounding mode.
|
||||
* @throws ArithmeticException if the rounding is needed, but the rounding mode is [java.math.RoundingMode.UNNECESSARY].
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.jvm.JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toBigDecimal(mathContext: java.math.MathContext): java.math.BigDecimal =
|
||||
java.math.BigDecimal(this, mathContext)
|
||||
|
||||
/**
|
||||
* Parses the string as a [java.math.BigDecimal] number and returns the result
|
||||
* or `null` if the string is not a valid representation of a number.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.jvm.JvmVersion
|
||||
public fun String.toBigDecimalOrNull(): java.math.BigDecimal? =
|
||||
screenFloatValue(this) { it.toBigDecimal() }
|
||||
|
||||
/**
|
||||
* Parses the string as a [java.math.BigDecimal] number and returns the result
|
||||
* or `null` if the string is not a valid representation of a number.
|
||||
*
|
||||
* @param mathContext specifies the precision and the rounding mode.
|
||||
* @throws ArithmeticException if the rounding is needed, but the rounding mode is [java.math.RoundingMode.UNNECESSARY].
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.jvm.JvmVersion
|
||||
public fun String.toBigDecimalOrNull(mathContext: java.math.MathContext): java.math.BigDecimal? =
|
||||
screenFloatValue(this) { it.toBigDecimal(mathContext) }
|
||||
|
||||
/**
|
||||
* Recommended floating point number validation RegEx from the javadoc of `java.lang.Double.valueOf(String)`
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
private object ScreenFloatValueRegEx {
|
||||
@JvmField val value = run {
|
||||
val Digits = "(\\p{Digit}+)"
|
||||
val HexDigits = "(\\p{XDigit}+)"
|
||||
val Exp = "[eE][+-]?$Digits"
|
||||
|
||||
val HexString = "(0[xX]$HexDigits(\\.)?)|" + // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
|
||||
"(0[xX]$HexDigits?(\\.)$HexDigits)" // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
|
||||
|
||||
val Number = "($Digits(\\.)?($Digits?)($Exp)?)|" + // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
|
||||
"(\\.($Digits)($Exp)?)|" + // . Digits ExponentPart_opt FloatTypeSuffix_opt
|
||||
"(($HexString)[pP][+-]?$Digits)" // HexSignificand BinaryExponent
|
||||
|
||||
val fpRegex = "[\\x00-\\x20]*[+-]?(NaN|Infinity|(($Number)[fFdD]?))[\\x00-\\x20]*"
|
||||
|
||||
Regex(fpRegex)
|
||||
}
|
||||
}
|
||||
|
||||
@kotlin.jvm.JvmVersion
|
||||
private inline fun <T> screenFloatValue(str: String, parse: (String) -> T): T? {
|
||||
return try {
|
||||
if (ScreenFloatValueRegEx.value.matches(str))
|
||||
parse(str)
|
||||
else
|
||||
null
|
||||
} catch(e: NumberFormatException) { // overflow
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -1,440 +0,0 @@
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("StringsKt")
|
||||
@file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
|
||||
|
||||
package kotlin.text
|
||||
|
||||
import java.nio.charset.Charset
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
|
||||
|
||||
/**
|
||||
* Returns the index within this string of the first occurrence of the specified character, starting from the specified offset.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
internal inline fun String.nativeIndexOf(ch: Char, fromIndex: Int): Int = (this as java.lang.String).indexOf(ch.toInt(), fromIndex)
|
||||
|
||||
/**
|
||||
* Returns the index within this string of the first occurrence of the specified substring, starting from the specified offset.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
internal inline fun String.nativeIndexOf(str: String, fromIndex: Int): Int = (this as java.lang.String).indexOf(str, fromIndex)
|
||||
|
||||
/**
|
||||
* Returns the index within this string of the last occurrence of the specified character.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
internal inline fun String.nativeLastIndexOf(ch: Char, fromIndex: Int): Int = (this as java.lang.String).lastIndexOf(ch.toInt(), fromIndex)
|
||||
|
||||
/**
|
||||
* Returns the index within this string of the last occurrence of the specified character, starting from the specified offset.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
internal inline fun String.nativeLastIndexOf(str: String, fromIndex: Int): Int = (this as java.lang.String).lastIndexOf(str, fromIndex)
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
if (this === null)
|
||||
return other === null
|
||||
return if (!ignoreCase)
|
||||
(this as java.lang.String).equals(other)
|
||||
else
|
||||
(this as java.lang.String).equalsIgnoreCase(other)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new string with all occurrences of [oldChar] replaced with [newChar].
|
||||
*/
|
||||
public fun String.replace(oldChar: Char, newChar: Char, ignoreCase: Boolean = false): String {
|
||||
if (!ignoreCase)
|
||||
return (this as java.lang.String).replace(oldChar, newChar)
|
||||
else
|
||||
return splitToSequence(oldChar, ignoreCase = ignoreCase).joinToString(separator = newChar.toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 =
|
||||
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 {
|
||||
val index = indexOf(oldChar, ignoreCase = ignoreCase)
|
||||
return if (index < 0) this else this.replaceRange(index, index + 1, newChar.toString())
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
val index = indexOf(oldValue, ignoreCase = ignoreCase)
|
||||
return if (index < 0) this else this.replaceRange(index, index + oldValue.length, newValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this string converted to upper case using the rules of the default locale.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toUpperCase(): String = (this as java.lang.String).toUpperCase()
|
||||
|
||||
/**
|
||||
* Returns a copy of this string converted to lower case using the rules of the default locale.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toLowerCase(): String = (this as java.lang.String).toLowerCase()
|
||||
|
||||
/**
|
||||
* Returns a new character array containing the characters from this string.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toCharArray(): CharArray = (this as java.lang.String).toCharArray()
|
||||
|
||||
/**
|
||||
* Copies characters from this string into the [destination] character array and returns that array.
|
||||
*
|
||||
* @param destination the array to copy to.
|
||||
* @param destinationOffset the position in the array to copy to.
|
||||
* @param startIndex the start offset (inclusive) of the substring to copy.
|
||||
* @param endIndex the end offset (exclusive) of the substring to copy.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toCharArray(destination: CharArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = length): CharArray {
|
||||
(this as java.lang.String).getChars(startIndex, endIndex, destination, destinationOffset)
|
||||
return destination
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses this string as a format string and returns a string obtained by substituting the specified arguments,
|
||||
* using the default locale.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.format(vararg args: Any?): String = java.lang.String.format(this, *args)
|
||||
|
||||
/**
|
||||
* Uses the provided [format] as a format string and returns a string obtained by substituting the specified arguments,
|
||||
* using the default locale.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.Companion.format(format: String, vararg args: Any?): String = java.lang.String.format(format, *args)
|
||||
|
||||
/**
|
||||
* Uses this string as a format string and returns a string obtained by substituting the specified arguments,
|
||||
* using the specified locale.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.format(locale: Locale, vararg args : Any?) : String = java.lang.String.format(locale, this, *args)
|
||||
|
||||
/**
|
||||
* Uses the provided [format] as a format string and returns a string obtained by substituting the specified arguments,
|
||||
* using the specified locale.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.Companion.format(locale: Locale, format: String, vararg args: Any?): String = java.lang.String.format(locale, format, *args)
|
||||
|
||||
/**
|
||||
* Splits this char sequence around matches of the given regular expression.
|
||||
|
||||
* @param limit Non-negative value specifying the maximum number of substrings to return.
|
||||
* Zero by default means no limit is set.
|
||||
*/
|
||||
public fun CharSequence.split(regex: Pattern, limit: Int = 0): List<String>
|
||||
{
|
||||
require(limit >= 0, { "Limit must be non-negative, but was $limit." } )
|
||||
return regex.split(this, if (limit == 0) -1 else limit).asList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a substring of this string that starts at the specified [startIndex] and continues to the end of the string.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.substring(startIndex: Int): String = (this as java.lang.String).substring(startIndex)
|
||||
|
||||
/**
|
||||
* Returns the substring of this string starting at the [startIndex] and ending right before the [endIndex].
|
||||
*
|
||||
* @param startIndex the start index (inclusive).
|
||||
* @param endIndex the end index (exclusive).
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.substring(startIndex: Int, endIndex: Int): String = (this as java.lang.String).substring(startIndex, endIndex)
|
||||
|
||||
/**
|
||||
* Returns `true` if this string starts with the specified prefix.
|
||||
*/
|
||||
public fun String.startsWith(prefix: String, ignoreCase: Boolean = false): Boolean {
|
||||
if (!ignoreCase)
|
||||
return (this as java.lang.String).startsWith(prefix)
|
||||
else
|
||||
return regionMatches(0, prefix, 0, prefix.length, ignoreCase)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if a substring of this string starting at the specified offset [startIndex] starts with the specified prefix.
|
||||
*/
|
||||
public fun String.startsWith(prefix: String, startIndex: Int, ignoreCase: Boolean = false): Boolean {
|
||||
if (!ignoreCase)
|
||||
return (this as java.lang.String).startsWith(prefix, startIndex)
|
||||
else
|
||||
return regionMatches(startIndex, prefix, 0, prefix.length, ignoreCase)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if this string ends with the specified suffix.
|
||||
*/
|
||||
public fun String.endsWith(suffix: String, ignoreCase: Boolean = false): Boolean {
|
||||
if (!ignoreCase)
|
||||
return (this as java.lang.String).endsWith(suffix)
|
||||
else
|
||||
return regionMatches(length - suffix.length, suffix, 0, suffix.length, ignoreCase = true)
|
||||
}
|
||||
|
||||
// "constructors" for String
|
||||
|
||||
/**
|
||||
* Converts the data from a portion of the specified array of bytes to characters using the specified character set
|
||||
* and returns the conversion result as a string.
|
||||
*
|
||||
* @param bytes the source array for the conversion.
|
||||
* @param offset the offset in the array of the data to be converted.
|
||||
* @param length the number of bytes to be converted.
|
||||
* @param charset the character set to use.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String(bytes: ByteArray, offset: Int, length: Int, charset: Charset): String = java.lang.String(bytes, offset, length, charset) as String
|
||||
|
||||
/**
|
||||
* Converts the data from the specified array of bytes to characters using the specified character set
|
||||
* and returns the conversion result as a string.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String(bytes: ByteArray, charset: Charset): String = java.lang.String(bytes, charset) as String
|
||||
|
||||
/**
|
||||
* Converts the data from a portion of the specified array of bytes to characters using the UTF-8 character set
|
||||
* and returns the conversion result as a string.
|
||||
*
|
||||
* @param bytes the source array for the conversion.
|
||||
* @param offset the offset in the array of the data to be converted.
|
||||
* @param length the number of bytes to be converted.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String(bytes: ByteArray, offset: Int, length: Int): String = java.lang.String(bytes, offset, length, Charsets.UTF_8) as String
|
||||
|
||||
/**
|
||||
* Converts the data from the specified array of bytes to characters using the UTF-8 character set
|
||||
* and returns the conversion result as a string.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String(bytes: ByteArray): String = java.lang.String(bytes, Charsets.UTF_8) as String
|
||||
|
||||
/**
|
||||
* Converts the characters in the specified array to a string.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String(chars: CharArray): String = java.lang.String(chars) as String
|
||||
|
||||
/**
|
||||
* Converts the characters from a portion of the specified array to a string.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String(chars: CharArray, offset: Int, length: Int): String = java.lang.String(chars, offset, length) as String
|
||||
|
||||
/**
|
||||
* Converts the code points from a portion of the specified Unicode code point array to a string.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String(codePoints: IntArray, offset: Int, length: Int): String = java.lang.String(codePoints, offset, length) as String
|
||||
|
||||
/**
|
||||
* Converts the contents of the specified StringBuffer to a string.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String(stringBuffer: java.lang.StringBuffer): String = java.lang.String(stringBuffer) as String
|
||||
|
||||
/**
|
||||
* Converts the contents of the specified StringBuilder to a string.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String(stringBuilder: java.lang.StringBuilder): String = java.lang.String(stringBuilder) as String
|
||||
|
||||
/**
|
||||
* Returns the character (Unicode code point) at the specified index.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.codePointAt(index: Int): Int = (this as java.lang.String).codePointAt(index)
|
||||
|
||||
/**
|
||||
* Returns the character (Unicode code point) before the specified index.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.codePointBefore(index: Int): Int = (this as java.lang.String).codePointBefore(index)
|
||||
|
||||
/**
|
||||
* Returns the number of Unicode code points in the specified text range of this String.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.codePointCount(beginIndex: Int, endIndex: Int): Int = (this as java.lang.String).codePointCount(beginIndex, endIndex)
|
||||
|
||||
/**
|
||||
* Compares two strings lexicographically, optionally ignoring case differences.
|
||||
*/
|
||||
public fun String.compareTo(other: String, ignoreCase: Boolean = false): Int {
|
||||
if (ignoreCase)
|
||||
return (this as java.lang.String).compareToIgnoreCase(other)
|
||||
else
|
||||
return (this as java.lang.String).compareTo(other)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if this string is equal to the contents of the specified CharSequence.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.contentEquals(charSequence: CharSequence): Boolean = (this as java.lang.String).contentEquals(charSequence)
|
||||
|
||||
/**
|
||||
* Returns `true` if this string is equal to the contents of the specified StringBuffer.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.contentEquals(stringBuilder: StringBuffer): Boolean = (this as java.lang.String).contentEquals(stringBuilder)
|
||||
|
||||
/**
|
||||
* Returns a canonical representation for this string object.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.intern(): String = (this as java.lang.String).intern()
|
||||
|
||||
/**
|
||||
* 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() }
|
||||
|
||||
/**
|
||||
* Returns the index within this string that is offset from the given [index] by [codePointOffset] code points.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.offsetByCodePoints(index: Int, codePointOffset: Int): Int = (this as java.lang.String).offsetByCodePoints(index, codePointOffset)
|
||||
|
||||
/**
|
||||
* Returns `true` if the specified range in this char sequence is equal to the specified range in another char sequence.
|
||||
* @param thisOffset the start offset in this char sequence of the substring to compare.
|
||||
* @param other the string against a substring of which the comparison is performed.
|
||||
* @param otherOffset the start offset in the other char sequence of the substring to compare.
|
||||
* @param length the length of the substring to compare.
|
||||
*/
|
||||
public fun CharSequence.regionMatches(thisOffset: Int, other: CharSequence, otherOffset: Int, length: Int, ignoreCase: Boolean = false): Boolean {
|
||||
if (this is String && other is String)
|
||||
return this.regionMatches(thisOffset, other, otherOffset, length, ignoreCase)
|
||||
else
|
||||
return regionMatchesImpl(thisOffset, other, otherOffset, length, ignoreCase)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the specified range in this string is equal to the specified range in another string.
|
||||
* @param thisOffset the start offset in this string of the substring to compare.
|
||||
* @param other the string against a substring of which the comparison is performed.
|
||||
* @param otherOffset the start offset in the other string of the substring to compare.
|
||||
* @param length the length of the substring to compare.
|
||||
*/
|
||||
public fun String.regionMatches(thisOffset: Int, other: String, otherOffset: Int, length: Int, ignoreCase: Boolean = false): Boolean =
|
||||
if (!ignoreCase)
|
||||
(this as java.lang.String).regionMatches(thisOffset, other, otherOffset, length)
|
||||
else
|
||||
(this as java.lang.String).regionMatches(ignoreCase, thisOffset, other, otherOffset, length)
|
||||
|
||||
/**
|
||||
* Returns a copy of this string converted to lower case using the rules of the specified locale.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toLowerCase(locale: java.util.Locale): String = (this as java.lang.String).toLowerCase(locale)
|
||||
|
||||
/**
|
||||
* Returns a copy of this string converted to upper case using the rules of the specified locale.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toUpperCase(locale: java.util.Locale): String = (this as java.lang.String).toUpperCase(locale)
|
||||
|
||||
/**
|
||||
* Encodes the contents of this string using the specified character set and returns the resulting byte array.
|
||||
* @sample samples.text.Strings.stringToByteArray
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toByteArray(charset: Charset = Charsets.UTF_8): ByteArray = (this as java.lang.String).getBytes(charset)
|
||||
|
||||
/**
|
||||
* Converts the string into a regular expression [Pattern] optionally
|
||||
* with the specified [flags] from [Pattern] or'd together
|
||||
* so that strings can be split or matched on.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun String.toPattern(flags: Int = 0): java.util.regex.Pattern {
|
||||
return java.util.regex.Pattern.compile(this, flags)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this string having its first letter uppercased, or the original string,
|
||||
* if it's empty or already starts with an upper case letter.
|
||||
*
|
||||
* @sample samples.text.Strings.capitalize
|
||||
*/
|
||||
public fun String.capitalize(): String {
|
||||
return if (isNotEmpty() && this[0].isLowerCase()) substring(0, 1).toUpperCase() + substring(1) else this
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this string having its first letter lowercased, or the original string,
|
||||
* if it's empty or already starts with a lower case letter.
|
||||
*
|
||||
* @sample samples.text.Strings.decapitalize
|
||||
*/
|
||||
public fun String.decapitalize(): String {
|
||||
return if (isNotEmpty() && this[0].isUpperCase()) substring(0, 1).toLowerCase() + substring(1) else this
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string containing this char sequence repeated [n] times.
|
||||
* @throws [IllegalArgumentException] when n < 0.
|
||||
* @sample samples.text.Strings.repeat
|
||||
*/
|
||||
public fun CharSequence.repeat(n: Int): String {
|
||||
require (n >= 0) { "Count 'n' must be non-negative, but was $n." }
|
||||
|
||||
return when (n) {
|
||||
0 -> ""
|
||||
1 -> this.toString()
|
||||
else -> {
|
||||
when (length) {
|
||||
0 -> ""
|
||||
1 -> this[0].let { char -> String(CharArray(n) { char }) }
|
||||
else -> {
|
||||
val sb = StringBuilder(n * length)
|
||||
for (i in 1..n) {
|
||||
sb.append(this)
|
||||
}
|
||||
sb.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A Comparator that orders strings ignoring character case.
|
||||
*
|
||||
* Note that this Comparator does not take locale into account,
|
||||
* and will result in an unsatisfactory ordering for certain locales.
|
||||
*/
|
||||
public val String.Companion.CASE_INSENSITIVE_ORDER: Comparator<String>
|
||||
get() = java.lang.String.CASE_INSENSITIVE_ORDER
|
||||
@@ -1,285 +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.
|
||||
*/
|
||||
@file:JvmVersion
|
||||
package kotlin.text
|
||||
|
||||
import java.util.Collections
|
||||
import java.util.EnumSet
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.internal.IMPLEMENTATIONS
|
||||
|
||||
private interface FlagEnum {
|
||||
public val value: Int
|
||||
public val mask: Int
|
||||
}
|
||||
private fun Iterable<FlagEnum>.toInt(): Int =
|
||||
this.fold(0, { value, option -> value or option.value })
|
||||
private inline fun <reified T> fromInt(value: Int): Set<T> where T : FlagEnum, T: Enum<T> =
|
||||
Collections.unmodifiableSet(EnumSet.allOf(T::class.java).apply {
|
||||
retainAll { value and it.mask == it.value }
|
||||
})
|
||||
|
||||
/**
|
||||
* Provides enumeration values to use to set regular expression options.
|
||||
*/
|
||||
public enum class RegexOption(override val value: Int, override val mask: Int = value) : FlagEnum {
|
||||
// common
|
||||
|
||||
/** Enables case-insensitive matching. Case comparison is Unicode-aware. */
|
||||
IGNORE_CASE(Pattern.CASE_INSENSITIVE),
|
||||
|
||||
/** Enables multiline mode.
|
||||
*
|
||||
* In multiline mode the expressions `^` and `$` match just after or just before,
|
||||
* respectively, a line terminator or the end of the input sequence. */
|
||||
MULTILINE(Pattern.MULTILINE),
|
||||
|
||||
//jvm-specific
|
||||
|
||||
/** Enables literal parsing of the pattern.
|
||||
*
|
||||
* Metacharacters or escape sequences in the input sequence will be given no special meaning.
|
||||
*/
|
||||
LITERAL(Pattern.LITERAL),
|
||||
|
||||
// // Unicode case is enabled by default with the IGNORE_CASE
|
||||
// /** Enables Unicode-aware case folding. */
|
||||
// UNICODE_CASE(Pattern.UNICODE_CASE)
|
||||
|
||||
/** Enables Unix lines mode.
|
||||
* In this mode, only the `'\n'` is recognized as a line terminator.
|
||||
*/
|
||||
UNIX_LINES(Pattern.UNIX_LINES),
|
||||
|
||||
/** Permits whitespace and comments in pattern. */
|
||||
COMMENTS(Pattern.COMMENTS),
|
||||
|
||||
/** Enables the mode, when the expression `.` matches any character,
|
||||
* including a line terminator.
|
||||
*/
|
||||
DOT_MATCHES_ALL(Pattern.DOTALL),
|
||||
|
||||
/** Enables equivalence by canonical decomposition. */
|
||||
CANON_EQ(Pattern.CANON_EQ)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents the results from a single capturing group within a [MatchResult] of [Regex].
|
||||
*
|
||||
* @param value The value of captured group.
|
||||
* @param range The range of indices in the input string where group was captured.
|
||||
*
|
||||
* The [range] property is available on JVM only.
|
||||
*/
|
||||
public data class MatchGroup(public val value: String, public val range: IntRange)
|
||||
|
||||
/**
|
||||
* Represents an immutable regular expression.
|
||||
*
|
||||
* For pattern syntax reference see [Pattern]
|
||||
*/
|
||||
public class Regex
|
||||
@PublishedApi
|
||||
internal constructor(private val nativePattern: Pattern) : Serializable {
|
||||
|
||||
|
||||
/** Creates a regular expression from the specified [pattern] string and the default options. */
|
||||
public constructor(pattern: String): this(Pattern.compile(pattern))
|
||||
|
||||
/** Creates a regular expression from the specified [pattern] string and the specified single [option]. */
|
||||
public constructor(pattern: String, option: RegexOption): this(Pattern.compile(pattern, ensureUnicodeCase(option.value)))
|
||||
|
||||
/** Creates a regular expression from the specified [pattern] string and the specified set of [options]. */
|
||||
public constructor(pattern: String, options: Set<RegexOption>): this(Pattern.compile(pattern, ensureUnicodeCase(options.toInt())))
|
||||
|
||||
|
||||
/** The pattern string of this regular expression. */
|
||||
public val pattern: String
|
||||
get() = nativePattern.pattern()
|
||||
|
||||
private var _options: Set<RegexOption>? = null
|
||||
/** The set of options that were used to create this regular expression. */
|
||||
public val options: Set<RegexOption> get() = _options ?: fromInt<RegexOption>(nativePattern.flags()).also { _options = it }
|
||||
|
||||
/** Indicates whether the regular expression matches the entire [input]. */
|
||||
public infix fun matches(input: CharSequence): Boolean = nativePattern.matcher(input).matches()
|
||||
|
||||
/** Indicates whether the regular expression can find at least one match in the specified [input]. */
|
||||
public fun containsMatchIn(input: CharSequence): Boolean = nativePattern.matcher(input).find()
|
||||
|
||||
/**
|
||||
* Returns the first match of a regular expression in the [input], beginning at the specified [startIndex].
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
public fun find(input: CharSequence, startIndex: Int = 0): MatchResult? = nativePattern.matcher(input).findNext(startIndex, input)
|
||||
|
||||
/**
|
||||
* Returns a sequence of all occurrences of a regular expression within the [input] string, beginning at the specified [startIndex].
|
||||
*/
|
||||
public fun findAll(input: CharSequence, startIndex: Int = 0): Sequence<MatchResult> = generateSequence({ find(input, startIndex) }, MatchResult::next)
|
||||
|
||||
/**
|
||||
* Attempts to match the entire [input] CharSequence against the pattern.
|
||||
*
|
||||
* @return An instance of [MatchResult] if the entire input matches or `null` otherwise.
|
||||
*/
|
||||
public fun matchEntire(input: CharSequence): MatchResult? = nativePattern.matcher(input).matchEntire(input)
|
||||
|
||||
/**
|
||||
* Replaces all occurrences of this regular expression in the specified [input] string with specified [replacement] expression.
|
||||
*
|
||||
* @param replacement A replacement expression that can include substitutions. See [Matcher.appendReplacement] for details.
|
||||
*/
|
||||
public fun replace(input: CharSequence, replacement: String): String = nativePattern.matcher(input).replaceAll(replacement)
|
||||
|
||||
/**
|
||||
* Replaces all occurrences of this regular expression in the specified [input] string with the result of
|
||||
* the given function [transform] that takes [MatchResult] and returns a string to be used as a
|
||||
* replacement for that match.
|
||||
*/
|
||||
public fun replace(input: CharSequence, transform: (MatchResult) -> CharSequence): String {
|
||||
var match: MatchResult? = find(input) ?: return input.toString()
|
||||
|
||||
var lastStart = 0
|
||||
val length = input.length
|
||||
val sb = StringBuilder(length)
|
||||
do {
|
||||
val foundMatch = match!!
|
||||
sb.append(input, lastStart, foundMatch.range.start)
|
||||
sb.append(transform(foundMatch))
|
||||
lastStart = foundMatch.range.endInclusive + 1
|
||||
match = foundMatch.next()
|
||||
} while (lastStart < length && match != null)
|
||||
|
||||
if (lastStart < length) {
|
||||
sb.append(input, lastStart, length)
|
||||
}
|
||||
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the first occurrence of this regular expression in the specified [input] string with specified [replacement] expression.
|
||||
*
|
||||
* @param replacement A replacement expression that can include substitutions. See [Matcher.appendReplacement] for details.
|
||||
*/
|
||||
public fun replaceFirst(input: CharSequence, replacement: String): String = nativePattern.matcher(input).replaceFirst(replacement)
|
||||
|
||||
|
||||
/**
|
||||
* Splits the [input] CharSequence around matches of this regular expression.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
public fun split(input: CharSequence, limit: Int = 0): List<String> {
|
||||
require(limit >= 0, { "Limit must be non-negative, but was $limit." } )
|
||||
return nativePattern.split(input, if (limit == 0) -1 else limit).asList()
|
||||
}
|
||||
|
||||
/** Returns the string representation of this regular expression, namely the [pattern] of this regular expression. */
|
||||
public override fun toString(): String = nativePattern.toString()
|
||||
|
||||
/**
|
||||
* Returns an instance of [Pattern] with the same pattern string and options as this instance of [Regex] has.
|
||||
*
|
||||
* Provides the way to use [Regex] where [Pattern] is required.
|
||||
*/
|
||||
public fun toPattern(): Pattern = nativePattern
|
||||
|
||||
private fun writeReplace(): Any = Serialized(nativePattern.pattern(), nativePattern.flags())
|
||||
|
||||
private class Serialized(val pattern: String, val flags: Int) : Serializable {
|
||||
companion object {
|
||||
private const val serialVersionUID: Long = 0L
|
||||
}
|
||||
|
||||
private fun readResolve(): Any = Regex(Pattern.compile(pattern, flags))
|
||||
}
|
||||
|
||||
companion object {
|
||||
/** Returns a literal regex for the specified [literal] string. */
|
||||
public fun fromLiteral(literal: String): Regex = literal.toRegex(RegexOption.LITERAL)
|
||||
/** Returns a literal pattern for the specified [literal] string. */
|
||||
public fun escape(literal: String): String = Pattern.quote(literal)
|
||||
/** Returns a literal replacement expression for the specified [literal] string. */
|
||||
public fun escapeReplacement(literal: String): String = Matcher.quoteReplacement(literal)
|
||||
|
||||
private fun ensureUnicodeCase(flags: Int) = if (flags and Pattern.CASE_INSENSITIVE != 0) flags or Pattern.UNICODE_CASE else flags
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// implementation
|
||||
|
||||
private fun Matcher.findNext(from: Int, input: CharSequence): MatchResult? {
|
||||
return if (!find(from)) null else MatcherMatchResult(this, input)
|
||||
}
|
||||
|
||||
private fun Matcher.matchEntire(input: CharSequence): MatchResult? {
|
||||
return if (!matches()) null else MatcherMatchResult(this, input)
|
||||
}
|
||||
|
||||
private class MatcherMatchResult(private val matcher: Matcher, private val input: CharSequence) : MatchResult {
|
||||
private val matchResult = matcher.toMatchResult()
|
||||
override val range: IntRange
|
||||
get() = matchResult.range()
|
||||
override val value: String
|
||||
get() = matchResult.group()
|
||||
|
||||
override val groups: MatchGroupCollection = object : MatchNamedGroupCollection, AbstractCollection<MatchGroup?>() {
|
||||
override val size: Int get() = matchResult.groupCount() + 1
|
||||
override fun isEmpty(): Boolean = false
|
||||
|
||||
override fun iterator(): Iterator<MatchGroup?> = indices.asSequence().map { this[it] }.iterator()
|
||||
override fun get(index: Int): MatchGroup? {
|
||||
val range = matchResult.range(index)
|
||||
return if (range.start >= 0)
|
||||
MatchGroup(matchResult.group(index), range)
|
||||
else
|
||||
null
|
||||
}
|
||||
override fun get(name: String): MatchGroup? {
|
||||
return IMPLEMENTATIONS.getMatchResultNamedGroup(matchResult, name)
|
||||
}
|
||||
}
|
||||
|
||||
private var groupValues_: List<String>? = null
|
||||
|
||||
override val groupValues: List<String>
|
||||
get() {
|
||||
if (groupValues_ == null) {
|
||||
groupValues_ = object : AbstractList<String>() {
|
||||
override val size: Int get() = matchResult.groupCount() + 1
|
||||
override fun get(index: Int): String = matchResult.group(index) ?: ""
|
||||
}
|
||||
}
|
||||
return groupValues_!!
|
||||
}
|
||||
|
||||
override fun next(): MatchResult? {
|
||||
val nextIndex = matchResult.end() + if (matchResult.end() == matchResult.start()) 1 else 0
|
||||
return if (nextIndex <= input.length) matcher.findNext(nextIndex, input) else null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun java.util.regex.MatchResult.range(): IntRange = start() until end()
|
||||
private fun java.util.regex.MatchResult.range(groupIndex: Int): IntRange = start(groupIndex) until end(groupIndex)
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("StringsKt")
|
||||
|
||||
package kotlin.text
|
||||
|
||||
|
||||
/**
|
||||
* Converts this [java.util.regex.Pattern] to an instance of [Regex].
|
||||
*
|
||||
* Provides the way to use Regex API on the instances of [java.util.regex.Pattern].
|
||||
*/
|
||||
@JvmVersion
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun java.util.regex.Pattern.toRegex(): Regex = Regex(this)
|
||||
@@ -1,33 +0,0 @@
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("PreconditionsKt")
|
||||
package kotlin
|
||||
|
||||
@PublishedApi
|
||||
internal object _Assertions {
|
||||
@JvmField @PublishedApi
|
||||
internal val ENABLED: Boolean = javaClass.desiredAssertionStatus()
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an [AssertionError] if the [value] is false
|
||||
* and runtime assertions have been enabled on the JVM using the *-ea* JVM option.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun assert(value: Boolean) {
|
||||
assert(value) { "Assertion failed" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an [AssertionError] calculated by [lazyMessage] if the [value] is false
|
||||
* and runtime assertions have been enabled on the JVM using the *-ea* JVM option.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun assert(value: Boolean, lazyMessage: () -> Any) {
|
||||
if (_Assertions.ENABLED) {
|
||||
if (!value) {
|
||||
val message = lazyMessage()
|
||||
throw AssertionError(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,157 +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.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("MathKt")
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
|
||||
package kotlin
|
||||
|
||||
import java.math.BigDecimal
|
||||
import java.math.MathContext
|
||||
import java.math.RoundingMode
|
||||
|
||||
/**
|
||||
* Enables the use of the `+` operator for [BigDecimal] instances.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigDecimal.plus(other: BigDecimal): BigDecimal = this.add(other)
|
||||
|
||||
/**
|
||||
* Enables the use of the `-` operator for [BigDecimal] instances.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigDecimal.minus(other: BigDecimal): BigDecimal = this.subtract(other)
|
||||
|
||||
/**
|
||||
* Enables the use of the `*` operator for [BigDecimal] instances.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigDecimal.times(other: BigDecimal): BigDecimal = this.multiply(other)
|
||||
|
||||
/**
|
||||
* Enables the use of the `/` operator for [BigDecimal] instances.
|
||||
*
|
||||
* The scale of the result is the same as the scale of `this` (divident), and for rounding the [RoundingMode.HALF_EVEN]
|
||||
* rounding mode is used.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigDecimal.div(other: BigDecimal): BigDecimal = this.divide(other, RoundingMode.HALF_EVEN)
|
||||
|
||||
/**
|
||||
* Enables the use of the `%` operator for [BigDecimal] instances.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
@Deprecated("Use rem(other) instead", ReplaceWith("rem(other)"), DeprecationLevel.WARNING)
|
||||
public inline operator fun BigDecimal.mod(other: BigDecimal): BigDecimal = this.remainder(other)
|
||||
|
||||
/**
|
||||
* Enables the use of the `%` operator for [BigDecimal] instances.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigDecimal.rem(other: BigDecimal): BigDecimal = this.remainder(other)
|
||||
|
||||
/**
|
||||
* Enables the use of the unary `-` operator for [BigDecimal] instances.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigDecimal.unaryMinus(): BigDecimal = this.negate()
|
||||
|
||||
/**
|
||||
* Enables the use of the unary `++` operator for [BigDecimal] instances.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigDecimal.inc(): BigDecimal = this.add(BigDecimal.ONE)
|
||||
|
||||
/**
|
||||
* Enables the use of the unary `--` operator for [BigDecimal] instances.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigDecimal.dec(): BigDecimal = this.subtract(BigDecimal.ONE)
|
||||
|
||||
/**
|
||||
* Returns the value of this [Int] number as a [BigDecimal].
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Int.toBigDecimal(): BigDecimal = BigDecimal.valueOf(this.toLong())
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of this [Int] number as a [BigDecimal].
|
||||
* @param mathContext specifies the precision and the rounding mode.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Int.toBigDecimal(mathContext: MathContext): BigDecimal = BigDecimal(this, mathContext)
|
||||
|
||||
/**
|
||||
* Returns the value of this [Long] number as a [BigDecimal].
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Long.toBigDecimal(): BigDecimal = BigDecimal.valueOf(this)
|
||||
|
||||
/**
|
||||
* Returns the value of this [Long] number as a [BigDecimal].
|
||||
* @param mathContext specifies the precision and the rounding mode.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Long.toBigDecimal(mathContext: MathContext): BigDecimal = BigDecimal(this, mathContext)
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of this [Float] number as a [BigDecimal].
|
||||
*
|
||||
* The number is converted to a string and then the string is converted to a [BigDecimal].
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Float.toBigDecimal(): BigDecimal = BigDecimal(this.toString())
|
||||
|
||||
/**
|
||||
* Returns the value of this [Float] number as a [BigDecimal].
|
||||
*
|
||||
* The number is converted to a string and then the string is converted to a [BigDecimal].
|
||||
*
|
||||
* @param mathContext specifies the precision and the rounding mode.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Float.toBigDecimal(mathContext: MathContext): BigDecimal = BigDecimal(this.toString(), mathContext)
|
||||
|
||||
/**
|
||||
* Returns the value of this [Double] number as a [BigDecimal].
|
||||
*
|
||||
* The number is converted to a string and then the string is converted to a [BigDecimal].
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Double.toBigDecimal(): BigDecimal = BigDecimal(this.toString())
|
||||
|
||||
/**
|
||||
* Returns the value of this [Double] number as a [BigDecimal].
|
||||
*
|
||||
* The number is converted to a string and then the string is converted to a [BigDecimal].
|
||||
*
|
||||
* @param mathContext specifies the precision and the rounding mode.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Double.toBigDecimal(mathContext: MathContext): BigDecimal = BigDecimal(this.toString(), mathContext)
|
||||
@@ -1,141 +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.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("MathKt")
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
|
||||
package kotlin
|
||||
|
||||
import java.math.BigInteger
|
||||
import java.math.BigDecimal
|
||||
import java.math.MathContext
|
||||
|
||||
/**
|
||||
* Enables the use of the `+` operator for [BigInteger] instances.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigInteger.plus(other: BigInteger): BigInteger = this.add(other)
|
||||
|
||||
/**
|
||||
* Enables the use of the `-` operator for [BigInteger] instances.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigInteger.minus(other: BigInteger): BigInteger = this.subtract(other)
|
||||
|
||||
/**
|
||||
* Enables the use of the `*` operator for [BigInteger] instances.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigInteger.times(other: BigInteger): BigInteger = this.multiply(other)
|
||||
|
||||
/**
|
||||
* Enables the use of the `/` operator for [BigInteger] instances.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigInteger.div(other: BigInteger): BigInteger = this.divide(other)
|
||||
|
||||
/**
|
||||
* Enables the use of the `%` operator for [BigInteger] instances.
|
||||
*/
|
||||
@SinceKotlin("1.1")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigInteger.rem(other: BigInteger): BigInteger = this.remainder(other)
|
||||
|
||||
/**
|
||||
* Enables the use of the unary `-` operator for [BigInteger] instances.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigInteger.unaryMinus(): BigInteger = this.negate()
|
||||
|
||||
/**
|
||||
* Enables the use of the `++` operator for [BigInteger] instances.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigInteger.inc(): BigInteger = this.add(BigInteger.ONE)
|
||||
|
||||
/**
|
||||
* Enables the use of the `--` operator for [BigInteger] instances.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline operator fun BigInteger.dec(): BigInteger = this.subtract(BigInteger.ONE)
|
||||
|
||||
/** Inverts the bits including the sign bit in this value. */
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun BigInteger.inv(): BigInteger = this.not()
|
||||
|
||||
/** Performs a bitwise AND operation between the two values. */
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline infix fun BigInteger.and(other: BigInteger): BigInteger = this.and(other)
|
||||
|
||||
/** Performs a bitwise OR operation between the two values. */
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline infix fun BigInteger.or(other: BigInteger): BigInteger = this.or(other)
|
||||
|
||||
/** Performs a bitwise XOR operation between the two values. */
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline infix fun BigInteger.xor(other: BigInteger): BigInteger = this.xor(other)
|
||||
|
||||
/** Shifts this value left by the [n] number of bits. */
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline infix fun BigInteger.shl(n: Int): BigInteger = this.shiftLeft(n)
|
||||
|
||||
/** Shifts this value right by the [n] number of bits, filling the leftmost bits with copies of the sign bit. */
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline infix fun BigInteger.shr(n: Int): BigInteger = this.shiftRight(n)
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of this [Int] number as a [BigInteger].
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Int.toBigInteger(): BigInteger = BigInteger.valueOf(this.toLong())
|
||||
|
||||
/**
|
||||
* Returns the value of this [Long] number as a [BigInteger].
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Long.toBigInteger(): BigInteger = BigInteger.valueOf(this)
|
||||
|
||||
/**
|
||||
* Returns the value of this [BigInteger] number as a [BigDecimal].
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun BigInteger.toBigDecimal(): BigDecimal = BigDecimal(this)
|
||||
|
||||
/**
|
||||
* Returns the value of this [BigInteger] number as a [BigDecimal]
|
||||
* scaled according to the specified [scale] and rounded according to the settings specified with [mathContext].
|
||||
*
|
||||
* @param scale the scale of the resulting [BigDecimal], i.e. number of decimal places of the fractional part.
|
||||
* By default 0.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun BigInteger.toBigDecimal(scale: Int = 0, mathContext: MathContext = MathContext.UNLIMITED): BigDecimal =
|
||||
BigDecimal(this, scale, mathContext)
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("ExceptionsKt")
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
@file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
|
||||
package kotlin
|
||||
|
||||
import java.io.PrintStream
|
||||
import java.io.PrintWriter
|
||||
import kotlin.internal.*
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this throwable to the standard output.
|
||||
*/
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") // to be used when no member available
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Throwable.printStackTrace(): Unit = (this as java.lang.Throwable).printStackTrace()
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this throwable to the specified [writer].
|
||||
*/
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") // to be used when no member available
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Throwable.printStackTrace(writer: PrintWriter): Unit = (this as java.lang.Throwable).printStackTrace(writer)
|
||||
|
||||
/**
|
||||
* Prints the stack trace of this throwable to the specified [stream].
|
||||
*/
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") // to be used when no member available
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Throwable.printStackTrace(stream: PrintStream): Unit = (this as java.lang.Throwable).printStackTrace(stream)
|
||||
|
||||
/**
|
||||
* Returns an array of stack trace elements representing the stack trace
|
||||
* pertaining to this throwable.
|
||||
*/
|
||||
@Suppress("ConflictingExtensionProperty")
|
||||
public val Throwable.stackTrace: Array<StackTraceElement>
|
||||
get() = (this as java.lang.Throwable).stackTrace!!
|
||||
|
||||
/**
|
||||
* When supported by the platform adds the specified exception to the list of exceptions that were
|
||||
* suppressed in order to deliver this exception.
|
||||
*/
|
||||
public fun Throwable.addSuppressed(exception: Throwable) = IMPLEMENTATIONS.addSuppressed(this, exception)
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:kotlin.jvm.JvmName("LazyKt")
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
|
||||
package kotlin
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]
|
||||
* and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED].
|
||||
*
|
||||
* If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access.
|
||||
*
|
||||
* Note that the returned instance uses itself to synchronize on. Do not synchronize from external code on
|
||||
* the returned instance as it may cause accidental deadlock. Also this behavior can be changed in the future.
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
public fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)
|
||||
|
||||
/**
|
||||
* Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]
|
||||
* and thread-safety [mode].
|
||||
*
|
||||
* If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access.
|
||||
*
|
||||
* Note that when the [LazyThreadSafetyMode.SYNCHRONIZED] mode is specified the returned instance uses itself
|
||||
* to synchronize on. Do not synchronize from external code on the returned instance as it may cause accidental deadlock.
|
||||
* Also this behavior can be changed in the future.
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
public fun <T> lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy<T> =
|
||||
when (mode) {
|
||||
LazyThreadSafetyMode.SYNCHRONIZED -> SynchronizedLazyImpl(initializer)
|
||||
LazyThreadSafetyMode.PUBLICATION -> SafePublicationLazyImpl(initializer)
|
||||
LazyThreadSafetyMode.NONE -> UnsafeLazyImpl(initializer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]
|
||||
* and the default thread-safety mode [LazyThreadSafetyMode.SYNCHRONIZED].
|
||||
*
|
||||
* If the initialization of a value throws an exception, it will attempt to reinitialize the value at next access.
|
||||
*
|
||||
* The returned instance uses the specified [lock] object to synchronize on.
|
||||
* When the [lock] is not specified the instance uses itself to synchronize on,
|
||||
* in this case do not synchronize from external code on the returned instance as it may cause accidental deadlock.
|
||||
* Also this behavior can be changed in the future.
|
||||
*/
|
||||
@kotlin.jvm.JvmVersion
|
||||
public fun <T> lazy(lock: Any?, initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer, lock)
|
||||
|
||||
|
||||
|
||||
@JvmVersion
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
@kotlin.jvm.JvmVersion
|
||||
private class SafePublicationLazyImpl<out T>(initializer: () -> T) : Lazy<T>, Serializable {
|
||||
@Volatile 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() {
|
||||
val value = _value
|
||||
if (value !== UNINITIALIZED_VALUE) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return value as T
|
||||
}
|
||||
|
||||
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
|
||||
return newValue
|
||||
}
|
||||
}
|
||||
@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")
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,90 +0,0 @@
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("MathKt")
|
||||
@file:kotlin.jvm.JvmVersion
|
||||
package kotlin
|
||||
|
||||
/**
|
||||
* Returns `true` if the specified number is a
|
||||
* Not-a-Number (NaN) value, `false` otherwise.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Double.isNaN(): Boolean = java.lang.Double.isNaN(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if the specified number is a
|
||||
* Not-a-Number (NaN) value, `false` otherwise.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Float.isNaN(): Boolean = java.lang.Float.isNaN(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if this value is infinitely large in magnitude.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Double.isInfinite(): Boolean = java.lang.Double.isInfinite(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if this value is infinitely large in magnitude.
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Float.isInfinite(): Boolean = java.lang.Float.isInfinite(this)
|
||||
|
||||
/**
|
||||
* Returns `true` if the argument is a finite floating-point value; returns `false` otherwise (for `NaN` and infinity arguments).
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Double.isFinite(): Boolean = !isInfinite() && !isNaN()
|
||||
|
||||
/**
|
||||
* Returns `true` if the argument is a finite floating-point value; returns `false` otherwise (for `NaN` and infinity arguments).
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Float.isFinite(): Boolean = !isInfinite() && !isNaN()
|
||||
|
||||
/**
|
||||
* Returns a bit representation of the specified floating-point value as [Long]
|
||||
* according to the IEEE 754 floating-point "double format" bit layout.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Double.toBits(): Long = java.lang.Double.doubleToLongBits(this)
|
||||
|
||||
/**
|
||||
* Returns a bit representation of the specified floating-point value as [Long]
|
||||
* according to the IEEE 754 floating-point "double format" bit layout,
|
||||
* preserving `NaN` values exact layout.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Double.toRawBits(): Long = java.lang.Double.doubleToRawLongBits(this)
|
||||
|
||||
/**
|
||||
* 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 = java.lang.Double.longBitsToDouble(bits)
|
||||
|
||||
/**
|
||||
* Returns a bit representation of the specified floating-point value as [Int]
|
||||
* according to the IEEE 754 floating-point "single format" bit layout.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Float.toBits(): Int = java.lang.Float.floatToIntBits(this)
|
||||
|
||||
/**
|
||||
* Returns a bit representation of the specified floating-point value as [Int]
|
||||
* according to the IEEE 754 floating-point "single format" bit layout,
|
||||
* preserving `NaN` values exact layout.
|
||||
*/
|
||||
@SinceKotlin("1.2")
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun Float.toRawBits(): Int = java.lang.Float.floatToRawIntBits(this)
|
||||
|
||||
/**
|
||||
* 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 = java.lang.Float.intBitsToFloat(bits)
|
||||
@@ -1,22 +0,0 @@
|
||||
@file:JvmVersion
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("StandardKt")
|
||||
package kotlin
|
||||
|
||||
import kotlin.jvm.internal.unsafe.*
|
||||
|
||||
/**
|
||||
* Executes the given function [block] while holding the monitor of the given object [lock].
|
||||
*/
|
||||
@kotlin.internal.InlineOnly
|
||||
public inline fun <R> synchronized(lock: Any, block: () -> R): R {
|
||||
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE", "INVISIBLE_MEMBER")
|
||||
monitorEnter(lock)
|
||||
try {
|
||||
return block()
|
||||
}
|
||||
finally {
|
||||
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE", "INVISIBLE_MEMBER")
|
||||
monitorExit(lock)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user