stdlib-jvm: move JVM specific sources, add actual modifier where required

Update copyright path after moving JVM sources
This commit is contained in:
Ilya Gorbunov
2018-01-24 21:28:17 +03:00
parent 93f7a46ba4
commit 22255a5cc4
58 changed files with 238 additions and 234 deletions
@@ -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")
}
}
@@ -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)
}
}
-218
View File
@@ -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()) }
-120
View File
@@ -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()
}
-146
View File
@@ -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.")
}
}
-160
View File
@@ -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)
-135
View File
@@ -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)
}
}