Deprecate Char-to-Number conversions in stdlib (Native)

- Synchronize code of Ranges, Progressions, ProgressionIterators
- Suppress deprecations in regex implementation code

KT-23451
This commit is contained in:
Ilya Gorbunov
2021-04-07 04:50:55 +03:00
parent 833955e56d
commit 7cd306950a
30 changed files with 152 additions and 78 deletions
@@ -81,7 +81,7 @@ internal object nativeMemUtils {
val sourceArray = source.reinterpret<ShortVar>().ptr val sourceArray = source.reinterpret<ShortVar>().ptr
var index = 0 var index = 0
while (index < length) { while (index < length) {
dest[index] = sourceArray[index].toChar() dest[index] = sourceArray[index].toInt().toChar()
++index ++index
} }
} }
@@ -91,7 +91,7 @@ internal object nativeMemUtils {
val destArray = dest.reinterpret<ShortVar>().ptr val destArray = dest.reinterpret<ShortVar>().ptr
var index = 0 var index = 0
while (index < length) { while (index < length) {
destArray[index] = source[index].toShort() destArray[index] = source[index].code.toShort()
++index ++index
} }
} }
@@ -148,7 +148,7 @@ public fun CPointer<UShortVar>.toKStringFromUtf16(): String {
val chars = kotlin.CharArray(length) val chars = kotlin.CharArray(length)
var index = 0 var index = 0
while (index < length) { while (index < length) {
chars[index] = nativeBytes[index].toShort().toChar() chars[index] = nativeBytes[index].toInt().toChar()
++index ++index
} }
return chars.concatToString() return chars.concatToString()
@@ -56,7 +56,7 @@ class StringNativeTest {
} }
fun Char.hex(): String { fun Char.hex(): String {
return toInt().toString(16).padStart(4, '0') return code.toString(16).padStart(4, '0')
} }
val sigma = '\u03A3' val sigma = '\u03A3'
@@ -173,7 +173,7 @@ private fun categoryValueFrom(code: Int, ch: Int): Int {
* Returns the Unicode general category of this character as an Int. * Returns the Unicode general category of this character as an Int.
*/ */
internal fun Char.getCategoryValue(): Int { internal fun Char.getCategoryValue(): Int {
val ch = this.toInt() val ch = this.code
val index = binarySearchRange(rangeStart, ch) val index = binarySearchRange(rangeStart, ch)
val start = rangeStart[index] val start = rangeStart[index]
@@ -39,7 +39,7 @@ internal fun binarySearchRange(array: IntArray, needle: Int): Int {
* Returns `true` if this character is a digit. * Returns `true` if this character is a digit.
*/ */
internal fun Char.isDigitImpl(): Boolean { internal fun Char.isDigitImpl(): Boolean {
val ch = this.toInt() val ch = this.code
val index = binarySearchRange(rangeStart, ch) val index = binarySearchRange(rangeStart, ch)
val high = rangeStart[index] + 9 val high = rangeStart[index] + 9
return ch <= high return ch <= high
@@ -89,7 +89,7 @@ internal fun Char.isUpperCaseImpl(): Boolean {
* - `0` otherwise. * - `0` otherwise.
*/ */
private fun Char.getLetterType(): Int { private fun Char.getLetterType(): Int {
val ch = this.toInt() val ch = this.code
val index = binarySearchRange(rangeStart, ch) val index = binarySearchRange(rangeStart, ch)
val rangeStart = rangeStart[index] val rangeStart = rangeStart[index]
@@ -49,5 +49,5 @@ internal fun Int.lowercaseCodePoint(): Int {
} }
internal fun Char.lowercaseCharImpl(): Char { internal fun Char.lowercaseCharImpl(): Char {
return toInt().lowercaseCodePoint().toChar() return code.lowercaseCodePoint().toChar()
} }
@@ -35,7 +35,7 @@ internal fun Char.oneToManyUppercase(): String? {
return null return null
} }
val code = this.toInt() val code = this.code
val index = binarySearchRange(keys, code) val index = binarySearchRange(keys, code)
if (keys[index] == code) { if (keys[index] == code) {
return values[index] return values[index]
@@ -28,7 +28,7 @@ private val casedEnd = intArrayOf(
// Lu + Ll + Lt + Other_Lowercase + Other_Uppercase (PropList.txt of Unicode Character Database files) // Lu + Ll + Lt + Other_Lowercase + Other_Uppercase (PropList.txt of Unicode Character Database files)
// Declared internal for testing // Declared internal for testing
internal fun Int.isCased(): Boolean { internal fun Int.isCased(): Boolean {
if (this <= Char.MAX_VALUE.toInt()) { if (this <= Char.MAX_VALUE.code) {
when (toChar().getCategoryValue()) { when (toChar().getCategoryValue()) {
CharCategory.UPPERCASE_LETTER.value, CharCategory.UPPERCASE_LETTER.value,
CharCategory.LOWERCASE_LETTER.value, CharCategory.LOWERCASE_LETTER.value,
@@ -65,7 +65,7 @@ private val caseIgnorableEnd = intArrayOf(
// Mn + Me + Cf + Lm + Sk + Word_Break=MidLetter + Word_Break=MidNumLet + Word_Break=Single_Quote (WordBreakProperty.txt of Unicode Character Database files) // Mn + Me + Cf + Lm + Sk + Word_Break=MidLetter + Word_Break=MidNumLet + Word_Break=Single_Quote (WordBreakProperty.txt of Unicode Character Database files)
// Declared internal for testing // Declared internal for testing
internal fun Int.isCaseIgnorable(): Boolean { internal fun Int.isCaseIgnorable(): Boolean {
if (this <= Char.MAX_VALUE.toInt()) { if (this <= Char.MAX_VALUE.code) {
when (toChar().getCategoryValue()) { when (toChar().getCategoryValue()) {
CharCategory.NON_SPACING_MARK.value, CharCategory.NON_SPACING_MARK.value,
CharCategory.ENCLOSING_MARK.value, CharCategory.ENCLOSING_MARK.value,
@@ -86,7 +86,7 @@ private fun String.codePointBefore(index: Int): Int {
return Char.toCodePoint(high, low) return Char.toCodePoint(high, low)
} }
} }
return low.toInt() return low.code
} }
// \p{cased} (\p{case-ignorable})* Sigma !( (\p{case-ignorable})* \p{cased} ) // \p{cased} (\p{case-ignorable})* Sigma !( (\p{case-ignorable})* \p{cased} )
@@ -18,7 +18,7 @@ internal fun String.codePointAt(index: Int): Int {
return Char.toCodePoint(high, low) return Char.toCodePoint(high, low)
} }
} }
return high.toInt() return high.code
} }
internal fun Int.charCount(): Int = if (this >= Char.MIN_SUPPLEMENTARY_CODE_POINT) 2 else 1 internal fun Int.charCount(): Int = if (this >= Char.MIN_SUPPLEMENTARY_CODE_POINT) 2 else 1
@@ -13,7 +13,7 @@ package kotlin.text
// 4 ranges totally // 4 ranges totally
@OptIn(ExperimentalStdlibApi::class) @OptIn(ExperimentalStdlibApi::class)
internal fun Char.titlecaseCharImpl(): Char { internal fun Char.titlecaseCharImpl(): Char {
val code = this.toInt() val code = this.code
// Letters repeating <Lu, Lt, Ll> sequence and code of the Lt is a multiple of 3, e.g. <DŽ, Dž, dž> // Letters repeating <Lu, Lt, Ll> sequence and code of the Lt is a multiple of 3, e.g. <DŽ, Dž, dž>
if (code in 0x01c4..0x01cc || code in 0x01f1..0x01f3) { if (code in 0x01c4..0x01cc || code in 0x01f1..0x01f3) {
return (3 * ((code + 1) / 3)).toChar() return (3 * ((code + 1) / 3)).toChar()
@@ -68,5 +68,5 @@ internal fun Int.uppercaseCodePoint(): Int {
} }
internal fun Char.uppercaseCharImpl(): Char { internal fun Char.uppercaseCharImpl(): Char {
return toInt().uppercaseCodePoint().toChar() return code.uppercaseCodePoint().toChar()
} }
@@ -15,7 +15,7 @@ package kotlin.text
* Returns `true` if this character is a whitespace. * Returns `true` if this character is a whitespace.
*/ */
internal fun Char.isWhitespaceImpl(): Boolean { internal fun Char.isWhitespaceImpl(): Boolean {
val ch = this.toInt() val ch = this.code
return ch in 0x0009..0x000d return ch in 0x0009..0x000d
|| ch in 0x001c..0x0020 || ch in 0x001c..0x0020
|| ch == 0x00a0 || ch == 0x00a0
@@ -24,13 +24,13 @@ public class Char private constructor() : Comparable<Char> {
/** Adds the other Int value to this value resulting a Char. */ /** Adds the other Int value to this value resulting a Char. */
public inline operator fun plus(other: Int): Char = public inline operator fun plus(other: Int): Char =
(this.toInt() + other).toChar() (this.code + other).toChar()
/** Subtracts the other Char value from this value resulting an Int. */ /** Subtracts the other Char value from this value resulting an Int. */
public inline operator fun minus(other: Char): Int = public inline operator fun minus(other: Char): Int =
this.toInt() - other.toInt() this.code - other.code
/** Subtracts the other Int value from this value resulting a Char. */ /** Subtracts the other Int value from this value resulting a Char. */
public inline operator fun minus(other: Int): Char = public inline operator fun minus(other: Int): Char =
(this.toInt() - other).toChar() (this.code - other).toChar()
/** Increments this value. */ /** Increments this value. */
@TypedIntrinsic(IntrinsicType.INC) @TypedIntrinsic(IntrinsicType.INC)
@@ -45,23 +45,35 @@ public class Char private constructor() : Comparable<Char> {
} }
/** Returns the value of this character as a `Byte`. */ /** Returns the value of this character as a `Byte`. */
@Deprecated("Conversion of Char to Number is deprecated. Use Char.code property instead.", ReplaceWith("this.code.toByte()"))
@DeprecatedSinceKotlin(warningSince = "1.5")
@TypedIntrinsic(IntrinsicType.INT_TRUNCATE) @TypedIntrinsic(IntrinsicType.INT_TRUNCATE)
external public fun toByte(): Byte external public fun toByte(): Byte
/** Returns the value of this character as a `Char`. */ /** Returns the value of this character as a `Char`. */
public inline fun toChar(): Char = this public inline fun toChar(): Char = this
/** Returns the value of this character as a `Short`. */ /** Returns the value of this character as a `Short`. */
@Deprecated("Conversion of Char to Number is deprecated. Use Char.code property instead.", ReplaceWith("this.code.toShort()"))
@DeprecatedSinceKotlin(warningSince = "1.5")
@TypedIntrinsic(IntrinsicType.ZERO_EXTEND) @TypedIntrinsic(IntrinsicType.ZERO_EXTEND)
external public fun toShort(): Short external public fun toShort(): Short
/** Returns the value of this character as a `Int`. */ /** Returns the value of this character as a `Int`. */
@Deprecated("Conversion of Char to Number is deprecated. Use Char.code property instead.", ReplaceWith("this.code"))
@DeprecatedSinceKotlin(warningSince = "1.5")
@TypedIntrinsic(IntrinsicType.ZERO_EXTEND) @TypedIntrinsic(IntrinsicType.ZERO_EXTEND)
external public fun toInt(): Int external public fun toInt(): Int
/** Returns the value of this character as a `Long`. */ /** Returns the value of this character as a `Long`. */
@Deprecated("Conversion of Char to Number is deprecated. Use Char.code property instead.", ReplaceWith("this.code.toLong()"))
@DeprecatedSinceKotlin(warningSince = "1.5")
@TypedIntrinsic(IntrinsicType.ZERO_EXTEND) @TypedIntrinsic(IntrinsicType.ZERO_EXTEND)
external public fun toLong(): Long external public fun toLong(): Long
/** Returns the value of this character as a `Float`. */ /** Returns the value of this character as a `Float`. */
@Deprecated("Conversion of Char to Number is deprecated. Use Char.code property instead.", ReplaceWith("this.code.toFloat()"))
@DeprecatedSinceKotlin(warningSince = "1.5")
@TypedIntrinsic(IntrinsicType.UNSIGNED_TO_FLOAT) @TypedIntrinsic(IntrinsicType.UNSIGNED_TO_FLOAT)
external public fun toFloat(): Float external public fun toFloat(): Float
/** Returns the value of this character as a `Double`. */ /** Returns the value of this character as a `Double`. */
@Deprecated("Conversion of Char to Number is deprecated. Use Char.code property instead.", ReplaceWith("this.code.toDouble()"))
@DeprecatedSinceKotlin(warningSince = "1.5")
@TypedIntrinsic(IntrinsicType.UNSIGNED_TO_FLOAT) @TypedIntrinsic(IntrinsicType.UNSIGNED_TO_FLOAT)
external public fun toDouble(): Double external public fun toDouble(): Double
@@ -155,7 +167,7 @@ public class Char private constructor() : Comparable<Char> {
external public override fun toString(): String external public override fun toString(): String
public override fun hashCode(): Int { public override fun hashCode(): Int {
return this.toInt(); return this.code
} }
} }
@@ -203,6 +203,8 @@ public final class Byte private constructor() : Number(), Comparable<Byte> {
* The least significant 8 bits of the resulting `Char` code are the same as the bits of this `Byte` value, * The least significant 8 bits of the resulting `Char` code are the same as the bits of this `Byte` value,
* whereas the most significant 8 bits are filled with the sign bit of this value. * whereas the most significant 8 bits are filled with the sign bit of this value.
*/ */
@Deprecated("Direct conversion to Char is deprecated. Use toInt().toChar() or Char constructor instead.", ReplaceWith("this.toInt().toChar()"))
@DeprecatedSinceKotlin(warningSince = "1.5")
@TypedIntrinsic(IntrinsicType.SIGN_EXTEND) @TypedIntrinsic(IntrinsicType.SIGN_EXTEND)
external public override fun toChar(): Char external public override fun toChar(): Char
/** /**
@@ -494,6 +496,8 @@ public final class Short private constructor() : Number(), Comparable<Short> {
* The resulting `Char` code is equal to this value reinterpreted as an unsigned number, * The resulting `Char` code is equal to this value reinterpreted as an unsigned number,
* i.e. it has the same binary representation as this `Short`. * i.e. it has the same binary representation as this `Short`.
*/ */
@Deprecated("Direct conversion to Char is deprecated. Use toInt().toChar() or Char constructor instead.", ReplaceWith("this.toInt().toChar()"))
@DeprecatedSinceKotlin(warningSince = "1.5")
@TypedIntrinsic(IntrinsicType.ZERO_EXTEND) @TypedIntrinsic(IntrinsicType.ZERO_EXTEND)
external public override fun toChar(): Char external public override fun toChar(): Char
@@ -1080,6 +1084,8 @@ public final class Long private constructor() : Number(), Comparable<Long> {
* *
* The resulting `Char` code is represented by the least significant 16 bits of this `Long` value. * The resulting `Char` code is represented by the least significant 16 bits of this `Long` value.
*/ */
@Deprecated("Direct conversion to Char is deprecated. Use toInt().toChar() or Char constructor instead.", ReplaceWith("this.toInt().toChar()"))
@DeprecatedSinceKotlin(warningSince = "1.5")
@TypedIntrinsic(IntrinsicType.INT_TRUNCATE) @TypedIntrinsic(IntrinsicType.INT_TRUNCATE)
external public override fun toChar(): Char external public override fun toChar(): Char
/** /**
@@ -1355,6 +1361,8 @@ public final class Float private constructor() : Number(), Comparable<Float> {
* *
* The resulting `Char` value is equal to `this.toInt().toChar()`. * The resulting `Char` value is equal to `this.toInt().toChar()`.
*/ */
@Deprecated("Direct conversion to Char is deprecated. Use toInt().toChar() or Char constructor instead.", ReplaceWith("this.toInt().toChar()"))
@DeprecatedSinceKotlin(warningSince = "1.5")
public override fun toChar(): Char = this.toInt().toChar() public override fun toChar(): Char = this.toInt().toChar()
/** /**
@@ -1631,6 +1639,8 @@ public final class Double private constructor() : Number(), Comparable<Double> {
* *
* The resulting `Char` value is equal to `this.toInt().toChar()`. * The resulting `Char` value is equal to `this.toInt().toChar()`.
*/ */
@Deprecated("Direct conversion to Char is deprecated. Use toInt().toChar() or Char constructor instead.", ReplaceWith("this.toInt().toChar()"))
@DeprecatedSinceKotlin(warningSince = "1.5")
public override fun toChar(): Char = this.toInt().toChar() public override fun toChar(): Char = this.toInt().toChar()
/** /**
@@ -184,7 +184,7 @@ internal fun checkProgressionStep(step: Long) =
@PublishedApi @PublishedApi
internal fun getProgressionLast(start: Char, end: Char, step: Int): Char = internal fun getProgressionLast(start: Char, end: Char, step: Int): Char =
getProgressionLast(start.toInt(), end.toInt(), step).toChar() getProgressionLast(start.code, end.code, step).toChar()
@PublishedApi @PublishedApi
internal fun getProgressionLast(start: Int, end: Int, step: Int): Int = internal fun getProgressionLast(start: Int, end: Int, step: Int): Int =
@@ -1,6 +1,6 @@
/* /*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* that can be found in the LICENSE file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
package kotlin.ranges package kotlin.ranges
@@ -10,9 +10,9 @@ package kotlin.ranges
* @property step the number by which the value is incremented on each step. * @property step the number by which the value is incremented on each step.
*/ */
internal class CharProgressionIterator(first: Char, last: Char, val step: Int) : CharIterator() { internal class CharProgressionIterator(first: Char, last: Char, val step: Int) : CharIterator() {
private val finalElement = last.toInt() private val finalElement: Int = last.code
private var hasNext: Boolean = if (step > 0) first <= last else first >= last private var hasNext: Boolean = if (step > 0) first <= last else first >= last
private var next = if (hasNext) first.toInt() else finalElement private var next: Int = if (hasNext) first.code else finalElement
override fun hasNext(): Boolean = hasNext override fun hasNext(): Boolean = hasNext
@@ -34,9 +34,9 @@ internal class CharProgressionIterator(first: Char, last: Char, val step: Int) :
* @property step the number by which the value is incremented on each step. * @property step the number by which the value is incremented on each step.
*/ */
internal class IntProgressionIterator(first: Int, last: Int, val step: Int) : IntIterator() { internal class IntProgressionIterator(first: Int, last: Int, val step: Int) : IntIterator() {
private val finalElement = last private val finalElement: Int = last
private var hasNext: Boolean = if (step > 0) first <= last else first >= last private var hasNext: Boolean = if (step > 0) first <= last else first >= last
private var next = if (hasNext) first else finalElement private var next: Int = if (hasNext) first else finalElement
override fun hasNext(): Boolean = hasNext override fun hasNext(): Boolean = hasNext
@@ -58,9 +58,9 @@ internal class IntProgressionIterator(first: Int, last: Int, val step: Int) : In
* @property step the number by which the value is incremented on each step. * @property step the number by which the value is incremented on each step.
*/ */
internal class LongProgressionIterator(first: Long, last: Long, val step: Long) : LongIterator() { internal class LongProgressionIterator(first: Long, last: Long, val step: Long) : LongIterator() {
private val finalElement = last private val finalElement: Long = last
private var hasNext: Boolean = if (step > 0) first <= last else first >= last private var hasNext: Boolean = if (step > 0) first <= last else first >= last
private var next = if (hasNext) first else finalElement private var next: Long = if (hasNext) first else finalElement
override fun hasNext(): Boolean = hasNext override fun hasNext(): Boolean = hasNext
@@ -76,3 +76,4 @@ internal class LongProgressionIterator(first: Long, last: Long, val step: Long)
return value return value
} }
} }
@@ -1,6 +1,6 @@
/* /*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* that can be found in the LICENSE file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
// A copy-paste from kotlin/core/builtins/src/kotlin/Progressions.kt // A copy-paste from kotlin/core/builtins/src/kotlin/Progressions.kt
@@ -13,12 +13,12 @@ import kotlin.internal.getProgressionLastElement
* A progression of values of type `Char`. * A progression of values of type `Char`.
*/ */
public open class CharProgression public open class CharProgression
internal constructor internal constructor
( (
start: Char, start: Char,
endInclusive: Char, endInclusive: Char,
step: Int step: Int
) : Iterable<Char> { ) : Iterable<Char> {
init { init {
if (step == 0) throw kotlin.IllegalArgumentException("Step must be non-zero.") if (step == 0) throw kotlin.IllegalArgumentException("Step must be non-zero.")
if (step == Int.MIN_VALUE) throw kotlin.IllegalArgumentException("Step must be greater than Int.MIN_VALUE to avoid overflow on negation.") if (step == Int.MIN_VALUE) throw kotlin.IllegalArgumentException("Step must be greater than Int.MIN_VALUE to avoid overflow on negation.")
@@ -32,7 +32,7 @@ internal constructor
/** /**
* The last element in the progression. * The last element in the progression.
*/ */
public val last: Char = getProgressionLastElement(start.toInt(), endInclusive.toInt(), step).toChar() public val last: Char = getProgressionLastElement(start.code, endInclusive.code, step).toChar()
/** /**
* The step of the progression. * The step of the progression.
@@ -41,15 +41,20 @@ internal constructor
override fun iterator(): CharIterator = CharProgressionIterator(first, last, step) override fun iterator(): CharIterator = CharProgressionIterator(first, last, step)
/** Checks if the progression is empty. */ /**
* Checks if the progression is empty.
* Progression with a positive step is empty if its first element is greater than the last element.
* Progression with a negative step is empty if its first element is less than the last element.
*/
public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last
override fun equals(other: Any?): Boolean = override fun equals(other: Any?): Boolean =
other is CharProgression && (isEmpty() && other.isEmpty() || other is CharProgression && (isEmpty() && other.isEmpty() ||
first == other.first && last == other.last && step == other.step) first == other.first && last == other.last && step == other.step)
override fun hashCode(): Int = override fun hashCode(): Int =
if (isEmpty()) -1 else (31 * (31 * first.toInt() + last.toInt()) + step) if (isEmpty()) -1 else (31 * (31 * first.code + last.code) + step)
override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}" override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}"
@@ -70,12 +75,12 @@ internal constructor
* A progression of values of type `Int`. * A progression of values of type `Int`.
*/ */
public open class IntProgression public open class IntProgression
internal constructor internal constructor
( (
start: Int, start: Int,
endInclusive: Int, endInclusive: Int,
step: Int step: Int
) : Iterable<Int> { ) : Iterable<Int> {
init { init {
if (step == 0) throw kotlin.IllegalArgumentException("Step must be non-zero.") if (step == 0) throw kotlin.IllegalArgumentException("Step must be non-zero.")
if (step == Int.MIN_VALUE) throw kotlin.IllegalArgumentException("Step must be greater than Int.MIN_VALUE to avoid overflow on negation.") if (step == Int.MIN_VALUE) throw kotlin.IllegalArgumentException("Step must be greater than Int.MIN_VALUE to avoid overflow on negation.")
@@ -89,7 +94,7 @@ internal constructor
/** /**
* The last element in the progression. * The last element in the progression.
*/ */
public val last: Int = getProgressionLastElement(start.toInt(), endInclusive.toInt(), step).toInt() public val last: Int = getProgressionLastElement(start, endInclusive, step)
/** /**
* The step of the progression. * The step of the progression.
@@ -98,15 +103,20 @@ internal constructor
override fun iterator(): IntIterator = IntProgressionIterator(first, last, step) override fun iterator(): IntIterator = IntProgressionIterator(first, last, step)
/** Checks if the progression is empty. */ /**
* Checks if the progression is empty.
* Progression with a positive step is empty if its first element is greater than the last element.
* Progression with a negative step is empty if its first element is less than the last element.
*/
public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last
override fun equals(other: Any?): Boolean = override fun equals(other: Any?): Boolean =
other is IntProgression && (isEmpty() && other.isEmpty() || other is IntProgression && (isEmpty() && other.isEmpty() ||
first == other.first && last == other.last && step == other.step) first == other.first && last == other.last && step == other.step)
override fun hashCode(): Int = override fun hashCode(): Int =
if (isEmpty()) -1 else (31 * (31 * first + last) + step) if (isEmpty()) -1 else (31 * (31 * first + last) + step)
override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}" override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}"
@@ -127,12 +137,12 @@ internal constructor
* A progression of values of type `Long`. * A progression of values of type `Long`.
*/ */
public open class LongProgression public open class LongProgression
internal constructor internal constructor
( (
start: Long, start: Long,
endInclusive: Long, endInclusive: Long,
step: Long step: Long
) : Iterable<Long> { ) : Iterable<Long> {
init { init {
if (step == 0L) throw kotlin.IllegalArgumentException("Step must be non-zero.") if (step == 0L) throw kotlin.IllegalArgumentException("Step must be non-zero.")
if (step == Long.MIN_VALUE) throw kotlin.IllegalArgumentException("Step must be greater than Long.MIN_VALUE to avoid overflow on negation.") if (step == Long.MIN_VALUE) throw kotlin.IllegalArgumentException("Step must be greater than Long.MIN_VALUE to avoid overflow on negation.")
@@ -146,7 +156,7 @@ internal constructor
/** /**
* The last element in the progression. * The last element in the progression.
*/ */
public val last: Long = getProgressionLastElement(start.toLong(), endInclusive.toLong(), step).toLong() public val last: Long = getProgressionLastElement(start, endInclusive, step)
/** /**
* The step of the progression. * The step of the progression.
@@ -155,15 +165,20 @@ internal constructor
override fun iterator(): LongIterator = LongProgressionIterator(first, last, step) override fun iterator(): LongIterator = LongProgressionIterator(first, last, step)
/** Checks if the progression is empty. */ /**
* Checks if the progression is empty.
* Progression with a positive step is empty if its first element is greater than the last element.
* Progression with a negative step is empty if its first element is less than the last element.
*/
public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last public open fun isEmpty(): Boolean = if (step > 0) first > last else first < last
override fun equals(other: Any?): Boolean = override fun equals(other: Any?): Boolean =
other is LongProgression && (isEmpty() && other.isEmpty() || other is LongProgression && (isEmpty() && other.isEmpty() ||
first == other.first && last == other.last && step == other.step) first == other.first && last == other.last && step == other.step)
override fun hashCode(): Int = override fun hashCode(): Int =
if (isEmpty()) -1 else (31 * (31 * (first xor (first ushr 32)) + (last xor (last ushr 32))) + (step xor (step ushr 32))).toInt() if (isEmpty()) -1 else (31 * (31 * (first xor (first ushr 32)) + (last xor (last ushr 32))) + (step xor (step ushr 32))).toInt()
override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}" override fun toString(): String = if (step > 0) "$first..$last step $step" else "$first downTo $last step ${-step}"
@@ -179,3 +194,4 @@ internal constructor
public fun fromClosedRange(rangeStart: Long, rangeEnd: Long, step: Long): LongProgression = LongProgression(rangeStart, rangeEnd, step) public fun fromClosedRange(rangeStart: Long, rangeEnd: Long, step: Long): LongProgression = LongProgression(rangeStart, rangeEnd, step)
} }
} }
@@ -27,6 +27,8 @@ public interface ClosedRange<T: Comparable<T>> {
/** /**
* Checks whether the range is empty. * Checks whether the range is empty.
* The range is empty if its start value is greater than the end value.
*/ */
public fun isEmpty(): Boolean = start > endInclusive public fun isEmpty(): Boolean = start > endInclusive
} }
@@ -1,6 +1,6 @@
/* /*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* that can be found in the LICENSE file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
package kotlin.ranges package kotlin.ranges
@@ -14,14 +14,19 @@ public class CharRange(start: Char, endInclusive: Char) : CharProgression(start,
override fun contains(value: Char): Boolean = first <= value && value <= last override fun contains(value: Char): Boolean = first <= value && value <= last
/**
* Checks whether the range is empty.
* The range is empty if its start value is greater than the end value.
*/
override fun isEmpty(): Boolean = first > last override fun isEmpty(): Boolean = first > last
override fun equals(other: Any?): Boolean = override fun equals(other: Any?): Boolean =
other is CharRange && (isEmpty() && other.isEmpty() || other is CharRange && (isEmpty() && other.isEmpty() ||
first == other.first && last == other.last) first == other.first && last == other.last)
override fun hashCode(): Int = override fun hashCode(): Int =
if (isEmpty()) -1 else (31 * first.toInt() + last.toInt()) if (isEmpty()) -1 else (31 * first.code + last.code)
override fun toString(): String = "$first..$last" override fun toString(): String = "$first..$last"
@@ -40,14 +45,19 @@ public class IntRange(start: Int, endInclusive: Int) : IntProgression(start, end
override fun contains(value: Int): Boolean = first <= value && value <= last override fun contains(value: Int): Boolean = first <= value && value <= last
/**
* Checks whether the range is empty.
* The range is empty if its start value is greater than the end value.
*/
override fun isEmpty(): Boolean = first > last override fun isEmpty(): Boolean = first > last
override fun equals(other: Any?): Boolean = override fun equals(other: Any?): Boolean =
other is IntRange && (isEmpty() && other.isEmpty() || other is IntRange && (isEmpty() && other.isEmpty() ||
first == other.first && last == other.last) first == other.first && last == other.last)
override fun hashCode(): Int = override fun hashCode(): Int =
if (isEmpty()) -1 else (31 * first + last) if (isEmpty()) -1 else (31 * first + last)
override fun toString(): String = "$first..$last" override fun toString(): String = "$first..$last"
@@ -66,14 +76,19 @@ public class LongRange(start: Long, endInclusive: Long) : LongProgression(start,
override fun contains(value: Long): Boolean = first <= value && value <= last override fun contains(value: Long): Boolean = first <= value && value <= last
/**
* Checks whether the range is empty.
* The range is empty if its start value is greater than the end value.
*/
override fun isEmpty(): Boolean = first > last override fun isEmpty(): Boolean = first > last
override fun equals(other: Any?): Boolean = override fun equals(other: Any?): Boolean =
other is LongRange && (isEmpty() && other.isEmpty() || other is LongRange && (isEmpty() && other.isEmpty() ||
first == other.first && last == other.last) first == other.first && last == other.last)
override fun hashCode(): Int = override fun hashCode(): Int =
if (isEmpty()) -1 else (31 * (first xor (first ushr 32)) + (last xor (last ushr 32))).toInt() if (isEmpty()) -1 else (31 * (first xor (first ushr 32)) + (last xor (last ushr 32))).toInt()
override fun toString(): String = "$first..$last" override fun toString(): String = "$first..$last"
@@ -82,3 +97,4 @@ public class LongRange(start: Long, endInclusive: Long) : LongProgression(start,
public val EMPTY: LongRange = LongRange(1, 0) public val EMPTY: LongRange = LongRange(1, 0)
} }
} }
@@ -264,6 +264,7 @@ internal actual fun checkRadix(radix: Int): Int {
/** Converts a unicode code point to lower case. */ /** Converts a unicode code point to lower case. */
internal fun Char.Companion.toLowerCase(codePoint: Int): Int = internal fun Char.Companion.toLowerCase(codePoint: Int): Int =
if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) { if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) {
@Suppress("DEPRECATION")
codePoint.toChar().toLowerCase().toInt() codePoint.toChar().toLowerCase().toInt()
} else { } else {
codePoint // TODO: Implement this transformation for supplementary codepoints. codePoint // TODO: Implement this transformation for supplementary codepoints.
@@ -272,19 +273,23 @@ internal fun Char.Companion.toLowerCase(codePoint: Int): Int =
/** Converts a unicode code point to upper case. */ /** Converts a unicode code point to upper case. */
internal fun Char.Companion.toUpperCase(codePoint: Int): Int = internal fun Char.Companion.toUpperCase(codePoint: Int): Int =
if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) { if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) {
@Suppress("DEPRECATION")
codePoint.toChar().toUpperCase().toInt() codePoint.toChar().toUpperCase().toInt()
} else { } else {
codePoint // TODO: Implement this transformation for supplementary codepoints. codePoint // TODO: Implement this transformation for supplementary codepoints.
} }
/** Converts a surrogate pair to a unicode code point. Doesn't validate that the characters are a valid surrogate pair. */ /** Converts a surrogate pair to a unicode code point. Doesn't validate that the characters are a valid surrogate pair. */
// TODO: Consider removing from public API
public fun Char.Companion.toCodePoint(high: Char, low: Char): Int = public fun Char.Companion.toCodePoint(high: Char, low: Char): Int =
(((high - MIN_HIGH_SURROGATE) shl 10) or (low - MIN_LOW_SURROGATE)) + 0x10000 (((high - MIN_HIGH_SURROGATE) shl 10) or (low - MIN_LOW_SURROGATE)) + 0x10000
/** Checks if the codepoint specified is a supplementary codepoint or not. */ /** Checks if the codepoint specified is a supplementary codepoint or not. */
// TODO: Consider removing from public API
public fun Char.Companion.isSupplementaryCodePoint(codepoint: Int): Boolean = public fun Char.Companion.isSupplementaryCodePoint(codepoint: Int): Boolean =
codepoint in MIN_SUPPLEMENTARY_CODE_POINT..MAX_CODE_POINT codepoint in MIN_SUPPLEMENTARY_CODE_POINT..MAX_CODE_POINT
// TODO: Consider removing from public API
public fun Char.Companion.isSurrogatePair(high: Char, low: Char): Boolean = high.isHighSurrogate() && low.isLowSurrogate() public fun Char.Companion.isSurrogatePair(high: Char, low: Char): Boolean = high.isHighSurrogate() && low.isLowSurrogate()
/** /**
@@ -292,6 +297,8 @@ public fun Char.Companion.isSurrogatePair(high: Char, low: Char): Boolean = high
* return an array with one element otherwise it will return an array A with a high surrogate in A[0] and * return an array with one element otherwise it will return an array A with a high surrogate in A[0] and
* a low surrogate in A[1]. * a low surrogate in A[1].
*/ */
// TODO: Consider removing from public API
@Suppress("DEPRECATION")
public fun Char.Companion.toChars(codePoint: Int): CharArray = public fun Char.Companion.toChars(codePoint: Int): CharArray =
when { when {
codePoint in 0 until MIN_SUPPLEMENTARY_CODE_POINT -> charArrayOf(codePoint.toChar()) codePoint in 0 until MIN_SUPPLEMENTARY_CODE_POINT -> charArrayOf(codePoint.toChar())
@@ -20,6 +20,7 @@
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("DEPRECATION") // Char.toInt()
package kotlin.text.regex package kotlin.text.regex
import kotlin.collections.associate import kotlin.collections.associate
@@ -20,6 +20,7 @@
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("DEPRECATION") // Char.toInt()
package kotlin.text.regex package kotlin.text.regex
private object unixLT : AbstractLineTerminator() { private object unixLT : AbstractLineTerminator() {
@@ -19,7 +19,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("DEPRECATION") // Char.toInt()
package kotlin.text.regex package kotlin.text.regex
/** /**
@@ -21,6 +21,7 @@
*/ */
// TODO: Licenses. // TODO: Licenses.
@file:Suppress("DEPRECATION") // Char.toInt()
package kotlin.text.regex package kotlin.text.regex
// Access to the decomposition tables. ========================================================================= // Access to the decomposition tables. =========================================================================
@@ -20,6 +20,7 @@
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("DEPRECATION") // Char.toInt()
package kotlin.text.regex package kotlin.text.regex
/** Represents a compiled pattern used by [Regex] for matching, searching, or replacing strings. */ /** Represents a compiled pattern used by [Regex] for matching, searching, or replacing strings. */
@@ -41,6 +41,7 @@ internal abstract class AbstractSet(val type: Int = 0) {
const val TYPE_LEAF = 1 shl 0 const val TYPE_LEAF = 1 shl 0
const val TYPE_FSET = 1 shl 1 const val TYPE_FSET = 1 shl 1
const val TYPE_QUANT = 1 shl 3 const val TYPE_QUANT = 1 shl 3
@Suppress("DEPRECATION")
const val TYPE_DOTSET = 0x80000000.toInt() or '.'.toInt() const val TYPE_DOTSET = 0x80000000.toInt() or '.'.toInt()
val dummyNext = object : AbstractSet() { val dummyNext = object : AbstractSet() {
@@ -139,9 +139,11 @@ open internal class DecomposedCharSet(
curChar = Char.toCodePoint(high, low) curChar = Char.toCodePoint(high, low)
readCharsForCodePoint = 2 readCharsForCodePoint = 2
} else { } else {
@Suppress("DEPRECATION")
curChar = high.toInt() curChar = high.toInt()
} }
} else { } else {
@Suppress("DEPRECATION")
curChar = testString[index].toInt() curChar = testString[index].toInt()
} }
@@ -20,6 +20,7 @@
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("DEPRECATION") // Char.toInt()
package kotlin.text.regex package kotlin.text.regex
import kotlin.text.* import kotlin.text.*
@@ -42,6 +42,7 @@ open internal class RangeSet(charClass: AbstractCharClass, val ignoreCase: Boole
get() = "range:" + (if (chars.alt) "^ " else " ") + chars.toString() get() = "range:" + (if (chars.alt) "^ " else " ") + chars.toString()
override fun first(set: AbstractSet): Boolean { override fun first(set: AbstractSet): Boolean {
@Suppress("DEPRECATION")
return when (set) { return when (set) {
is CharSet -> AbstractCharClass.intersects(chars, set.char.toInt()) is CharSet -> AbstractCharClass.intersects(chars, set.char.toInt())
is RangeSet -> AbstractCharClass.intersects(chars, set.chars) is RangeSet -> AbstractCharClass.intersects(chars, set.chars)
@@ -137,6 +137,7 @@ open internal class SupplementaryRangeSet(charClass: AbstractCharClass, val igno
override fun first(set: AbstractSet): Boolean { override fun first(set: AbstractSet): Boolean {
@Suppress("DEPRECATION")
return when(set) { return when(set) {
is SupplementaryCharSet -> AbstractCharClass.intersects(chars, set.codePoint) is SupplementaryCharSet -> AbstractCharClass.intersects(chars, set.codePoint)
is CharSet -> AbstractCharClass.intersects(chars, set.char.toInt()) is CharSet -> AbstractCharClass.intersects(chars, set.char.toInt())