Implement String to/from CharArray conversion (KT-29265)
This commit is contained in:
@@ -80,7 +80,8 @@ compileCoroutinesExperimentalKotlinCommon {
|
||||
compileTestKotlinCommon {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs += [
|
||||
"-Xuse-experimental=kotlin.ExperimentalUnsignedTypes"
|
||||
"-Xuse-experimental=kotlin.ExperimentalUnsignedTypes",
|
||||
"-Xuse-experimental=kotlin.ExperimentalStdlibApi"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,31 @@ public expect fun String(chars: CharArray): String
|
||||
@SinceKotlin("1.2")
|
||||
public expect fun String(chars: CharArray, offset: Int, length: Int): String
|
||||
|
||||
/**
|
||||
* Concatenates characters in this [CharArray] or its subrange into a String.
|
||||
*
|
||||
* @param startIndex the beginning (inclusive) of the subrange of characters, 0 by default.
|
||||
* @param endIndex the end (exclusive) of the subrange of characters, size of this array by default.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the size of this array.
|
||||
* @throws IllegalArgumentException if [startIndex] is greater than [endIndex].
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public expect fun CharArray.concatToString(startIndex: Int = 0, endIndex: Int = this.size): String
|
||||
|
||||
/**
|
||||
* Returns a [CharArray] containing characters of this string or its substring.
|
||||
*
|
||||
* @param startIndex the beginning (inclusive) of the substring, 0 by default.
|
||||
* @param endIndex the end (exclusive) of the substring, length of this string by default.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the length of this string.
|
||||
* @throws IllegalArgumentException if [startIndex] is greater than [endIndex].
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@ExperimentalStdlibApi
|
||||
public expect fun String.toCharArray(startIndex: Int = 0, endIndex: Int = this.length): CharArray
|
||||
|
||||
internal expect fun String.nativeIndexOf(str: String, fromIndex: Int): Int
|
||||
internal expect fun String.nativeLastIndexOf(str: String, fromIndex: Int): Int
|
||||
|
||||
@@ -91,7 +91,12 @@ compileKotlin {
|
||||
}
|
||||
|
||||
compileTestKotlin {
|
||||
kotlinOptions.freeCompilerArgs = ["-Xallow-kotlin-package", "-Xmulti-platform", "-Xuse-experimental=kotlin.ExperimentalUnsignedTypes"]
|
||||
kotlinOptions.freeCompilerArgs = [
|
||||
"-Xallow-kotlin-package",
|
||||
"-Xmulti-platform",
|
||||
"-Xuse-experimental=kotlin.ExperimentalUnsignedTypes",
|
||||
"-Xuse-experimental=kotlin.ExperimentalStdlibApi"
|
||||
]
|
||||
}
|
||||
|
||||
compileJava9Sources(project, 'kotlin.stdlib.jdk7')
|
||||
|
||||
@@ -85,7 +85,12 @@ compileKotlin {
|
||||
}
|
||||
|
||||
compileTestKotlin {
|
||||
kotlinOptions.freeCompilerArgs = ["-Xallow-kotlin-package", "-Xmulti-platform", "-Xuse-experimental=kotlin.ExperimentalUnsignedTypes"]
|
||||
kotlinOptions.freeCompilerArgs = [
|
||||
"-Xallow-kotlin-package",
|
||||
"-Xmulti-platform",
|
||||
"-Xuse-experimental=kotlin.ExperimentalUnsignedTypes",
|
||||
"-Xuse-experimental=kotlin.ExperimentalStdlibApi"
|
||||
]
|
||||
}
|
||||
|
||||
compileJava9Sources(project, 'kotlin.stdlib.jdk8')
|
||||
|
||||
@@ -135,7 +135,8 @@ compileTestKotlin2Js {
|
||||
"-Xir",
|
||||
"-Xir-produce-only=js",
|
||||
"-verbose",
|
||||
"-Xuse-experimental=kotlin.ExperimentalUnsignedTypes"
|
||||
"-Xuse-experimental=kotlin.ExperimentalUnsignedTypes",
|
||||
"-Xuse-experimental=kotlin.ExperimentalStdlibApi"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +193,8 @@ compileTestKotlin2Js {
|
||||
kotlinOptions {
|
||||
moduleKind = "umd"
|
||||
freeCompilerArgs += [
|
||||
"-Xuse-experimental=kotlin.ExperimentalUnsignedTypes"
|
||||
"-Xuse-experimental=kotlin.ExperimentalUnsignedTypes",
|
||||
"-Xuse-experimental=kotlin.ExperimentalStdlibApi"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,44 @@ public actual fun String(chars: CharArray, offset: Int, length: Int): String {
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates characters in this [CharArray] or its subrange into a String.
|
||||
*
|
||||
* @param startIndex the beginning (inclusive) of the subrange of characters, 0 by default.
|
||||
* @param endIndex the end (exclusive) of the subrange of characters, size of this array by default.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the size of this array.
|
||||
* @throws IllegalArgumentException if [startIndex] is greater than [endIndex].
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
|
||||
@ExperimentalStdlibApi
|
||||
public actual fun CharArray.concatToString(startIndex: Int = 0, endIndex: Int = this.size): String {
|
||||
AbstractList.checkBoundsIndexes(startIndex, endIndex, this.size)
|
||||
var result = ""
|
||||
for (index in startIndex until endIndex) {
|
||||
result += this[index]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [CharArray] containing characters of this string or its substring.
|
||||
*
|
||||
* @param startIndex the beginning (inclusive) of the substring, 0 by default.
|
||||
* @param endIndex the end (exclusive) of the substring, length of this string by default.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the length of this string.
|
||||
* @throws IllegalArgumentException if [startIndex] is greater than [endIndex].
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
|
||||
@ExperimentalStdlibApi
|
||||
public actual fun String.toCharArray(startIndex: Int = 0, endIndex: Int = this.length): CharArray {
|
||||
AbstractList.checkBoundsIndexes(startIndex, endIndex, length)
|
||||
return CharArray(endIndex - startIndex) { get(startIndex + it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this string converted to upper case using the rules of the default locale.
|
||||
*
|
||||
|
||||
@@ -249,7 +249,8 @@ check.dependsOn(coroutinesExperimentalMigrationTest)
|
||||
compileTestKotlin {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs += [
|
||||
"-Xuse-experimental=kotlin.ExperimentalUnsignedTypes"
|
||||
"-Xuse-experimental=kotlin.ExperimentalUnsignedTypes",
|
||||
"-Xuse-experimental=kotlin.ExperimentalStdlibApi"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
package kotlin.text
|
||||
|
||||
import java.nio.charset.Charset
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
import java.util.regex.Pattern
|
||||
|
||||
|
||||
@@ -108,6 +108,40 @@ public actual inline fun String.toUpperCase(): String = (this as java.lang.Strin
|
||||
@kotlin.internal.InlineOnly
|
||||
public actual inline fun String.toLowerCase(): String = (this as java.lang.String).toLowerCase()
|
||||
|
||||
/**
|
||||
* Concatenates characters in this [CharArray] or its subrange into a String.
|
||||
*
|
||||
* @param startIndex the beginning (inclusive) of the subrange of characters, 0 by default.
|
||||
* @param endIndex the end (exclusive) of the subrange of characters, size of this array by default.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the size of this array.
|
||||
* @throws IllegalArgumentException if [startIndex] is greater than [endIndex].
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
|
||||
@ExperimentalStdlibApi
|
||||
public actual fun CharArray.concatToString(startIndex: Int = 0, endIndex: Int = this.size): String {
|
||||
AbstractList.checkBoundsIndexes(startIndex, endIndex, this.size)
|
||||
return String(this, startIndex, endIndex - startIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a [CharArray] containing characters of this string or its substring.
|
||||
*
|
||||
* @param startIndex the beginning (inclusive) of the substring, 0 by default.
|
||||
* @param endIndex the end (exclusive) of the substring, length of this string by default.
|
||||
*
|
||||
* @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the length of this string.
|
||||
* @throws IllegalArgumentException if [startIndex] is greater than [endIndex].
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
|
||||
@ExperimentalStdlibApi
|
||||
public actual fun String.toCharArray(startIndex: Int = 0, endIndex: Int = this.length): CharArray {
|
||||
AbstractList.checkBoundsIndexes(startIndex, endIndex, length)
|
||||
return toCharArray(CharArray(endIndex - startIndex), 0, startIndex, endIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new character array containing the characters from this string.
|
||||
*/
|
||||
|
||||
@@ -123,6 +123,15 @@ public abstract class AbstractList<out E> protected constructor() : AbstractColl
|
||||
}
|
||||
}
|
||||
|
||||
internal fun checkBoundsIndexes(startIndex: Int, endIndex: Int, size: Int) {
|
||||
if (startIndex < 0 || endIndex > size) {
|
||||
throw IndexOutOfBoundsException("startIndex: $startIndex, endIndex: $endIndex, size: $size")
|
||||
}
|
||||
if (startIndex > endIndex) {
|
||||
throw IllegalArgumentException("startIndex: $startIndex > endIndex: $endIndex")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun orderedHashCode(c: Collection<*>): Int {
|
||||
var hashCode = 1
|
||||
for (e in c) {
|
||||
|
||||
@@ -45,36 +45,52 @@ fun Char.isAsciiUpperCase() = this in 'A'..'Z'
|
||||
|
||||
class StringTest {
|
||||
|
||||
private fun testStringFromChars(expected: String, chars: CharArray, offset: Int, length: Int) {
|
||||
assertEquals(expected, String(chars, offset, length))
|
||||
assertEquals(expected, chars.concatToString(startIndex = offset, endIndex = offset + length))
|
||||
}
|
||||
|
||||
private fun testStringFromChars(expected: String, chars: CharArray) {
|
||||
assertEquals(expected, String(chars))
|
||||
assertEquals(expected, chars.concatToString())
|
||||
}
|
||||
|
||||
@Test fun stringFromCharArrayFullSlice() {
|
||||
val chars: CharArray = charArrayOf('K', 'o', 't', 'l', 'i', 'n')
|
||||
assertEquals("Kotlin", String(chars, 0, chars.size))
|
||||
testStringFromChars("Kotlin", chars, 0, chars.size)
|
||||
}
|
||||
|
||||
@Test fun stringFromCharArraySlice() {
|
||||
val chars: CharArray = charArrayOf('K', 'o', 't', 'l', 'i', 'n', ' ', 'r', 'u', 'l', 'e', 's')
|
||||
assertEquals("rule", String(chars, 7, 4))
|
||||
testStringFromChars("rule", chars, 7, 4)
|
||||
|
||||
val longChars = CharArray(200_000) { 'k' }
|
||||
val longString = String(longChars, 1000, 190_000)
|
||||
val longString = String(longChars, offset = 1000, length = 190_000)
|
||||
val longConcatString = longChars.concatToString(startIndex = 1000, endIndex = 191_000)
|
||||
assertEquals(190_000, longString.length)
|
||||
assertEquals(190_000, longConcatString.length)
|
||||
assertTrue(longString.all { it == 'k' })
|
||||
assertTrue(longConcatString.all { it == 'k' })
|
||||
}
|
||||
|
||||
@Test fun stringFromCharArray() {
|
||||
val chars: CharArray = charArrayOf('K', 'o', 't', 'l', 'i', 'n')
|
||||
assertEquals("Kotlin", String(chars))
|
||||
testStringFromChars("Kotlin", chars)
|
||||
|
||||
val longChars = CharArray(200_000) { 'k' }
|
||||
val longString = String(longChars)
|
||||
val longConcatString = longChars.concatToString()
|
||||
assertEquals(200_000, longString.length)
|
||||
assertEquals(200_000, longConcatString.length)
|
||||
assertTrue(longString.all { it == 'k' })
|
||||
assertTrue(longConcatString.all { it == 'k' })
|
||||
}
|
||||
|
||||
@Test fun stringFromCharArrayUnicodeSurrogatePairs() {
|
||||
val chars: CharArray = charArrayOf('Ц', '月', '語', '\u016C', '\u138D', '\uD83C', '\uDC3A')
|
||||
assertEquals("Ц月語Ŭᎍ🀺", String(chars))
|
||||
assertEquals("月", String(chars, 1, 1))
|
||||
assertEquals("Ŭᎍ🀺", String(chars, 3, 4))
|
||||
testStringFromChars("Ц月語Ŭᎍ🀺", chars)
|
||||
testStringFromChars("月", chars, 1, 1)
|
||||
testStringFromChars("Ŭᎍ🀺", chars, 3, 4)
|
||||
}
|
||||
|
||||
@Test fun stringFromCharArrayOutOfBounds() {
|
||||
@@ -82,11 +98,26 @@ class StringTest {
|
||||
assertFailsWith<IndexOutOfBoundsException> { String(chars, -1, 1) }
|
||||
assertFailsWith<IndexOutOfBoundsException> { String(chars, 1, -1) }
|
||||
assertFailsWith<IndexOutOfBoundsException> { String(chars, chars.size - 1, 2) }
|
||||
|
||||
assertFailsWith<IndexOutOfBoundsException> { chars.concatToString(-1, 1) }
|
||||
assertFailsWith<IllegalArgumentException> { chars.concatToString(1, -1) }
|
||||
assertFailsWith<IllegalArgumentException> { chars.concatToString(chars.size - 1, 2) }
|
||||
}
|
||||
test(CharArray(16) { 'k' })
|
||||
test(CharArray(160_000) { 'k' })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun toCharArray() {
|
||||
val s = "hello"
|
||||
assertArrayContentEquals(charArrayOf('h', 'e', 'l', 'l', 'o'), s.toCharArray())
|
||||
assertArrayContentEquals(charArrayOf('e', 'l'), s.toCharArray(1, 3))
|
||||
|
||||
assertFailsWith<IndexOutOfBoundsException> { s.toCharArray(-1) }
|
||||
assertFailsWith<IndexOutOfBoundsException> { s.toCharArray(0, 6) }
|
||||
assertFailsWith<IllegalArgumentException> { s.toCharArray(3, 1) }
|
||||
}
|
||||
|
||||
@Test fun isEmptyAndBlank() = withOneCharSequenceArg { arg1 ->
|
||||
class Case(val value: String?, val isNull: Boolean = false, val isEmpty: Boolean = false, val isBlank: Boolean = false)
|
||||
|
||||
|
||||
+4
@@ -4906,6 +4906,8 @@ public final class kotlin/text/StringsKt {
|
||||
public static synthetic fun commonSuffixWith$default (Ljava/lang/CharSequence;Ljava/lang/CharSequence;ZILjava/lang/Object;)Ljava/lang/String;
|
||||
public static final fun compareTo (Ljava/lang/String;Ljava/lang/String;Z)I
|
||||
public static synthetic fun compareTo$default (Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)I
|
||||
public static final fun concatToString ([CII)Ljava/lang/String;
|
||||
public static synthetic fun concatToString$default ([CIIILjava/lang/Object;)Ljava/lang/String;
|
||||
public static final fun contains (Ljava/lang/CharSequence;CZ)Z
|
||||
public static final fun contains (Ljava/lang/CharSequence;Ljava/lang/CharSequence;Z)Z
|
||||
public static synthetic fun contains$default (Ljava/lang/CharSequence;CZILjava/lang/Object;)Z
|
||||
@@ -5131,6 +5133,8 @@ public final class kotlin/text/StringsKt {
|
||||
public static final fun toBigIntegerOrNull (Ljava/lang/String;I)Ljava/math/BigInteger;
|
||||
public static final fun toByteOrNull (Ljava/lang/String;)Ljava/lang/Byte;
|
||||
public static final fun toByteOrNull (Ljava/lang/String;I)Ljava/lang/Byte;
|
||||
public static final fun toCharArray (Ljava/lang/String;II)[C
|
||||
public static synthetic fun toCharArray$default (Ljava/lang/String;IIILjava/lang/Object;)[C
|
||||
public static final fun toCollection (Ljava/lang/CharSequence;Ljava/util/Collection;)Ljava/util/Collection;
|
||||
public static final fun toDoubleOrNull (Ljava/lang/String;)Ljava/lang/Double;
|
||||
public static final fun toFloatOrNull (Ljava/lang/String;)Ljava/lang/Float;
|
||||
|
||||
Reference in New Issue
Block a user