From ede2e227c2646d8e1416f79bf5245e8e45d2d2c6 Mon Sep 17 00:00:00 2001 From: Neonailol Date: Mon, 21 May 2018 17:15:00 +0300 Subject: [PATCH] KT-23356 Cross-platform function to convert CharArray slice to String Signed-off-by: Valeriy Zhirnov --- libraries/stdlib/common/src/kotlin/TextH.kt | 14 ++++++++++++ libraries/stdlib/js/src/kotlin/string.kt | 18 +++++++++++++++ .../stdlib/jvm/src/kotlin/text/StringsJVM.kt | 4 ++-- libraries/stdlib/test/text/StringTest.kt | 22 +++++++++++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/libraries/stdlib/common/src/kotlin/TextH.kt b/libraries/stdlib/common/src/kotlin/TextH.kt index d6f9a4d1d66..c7d8ffc0ab4 100644 --- a/libraries/stdlib/common/src/kotlin/TextH.kt +++ b/libraries/stdlib/common/src/kotlin/TextH.kt @@ -90,6 +90,20 @@ expect fun Char.isLowSurrogate(): Boolean // From string.kt + +/** + * Converts the characters in the specified array to a string. + */ +@SinceKotlin("1.2") +public expect fun String(chars: CharArray): String + +/** + * Converts the characters from a portion of the specified array to a string. + */ +@SinceKotlin("1.2") +public expect fun String(chars: CharArray, offset: Int, length: Int): String + + internal expect fun String.nativeIndexOf(str: String, fromIndex: Int): Int internal expect fun String.nativeLastIndexOf(str: String, fromIndex: Int): Int diff --git a/libraries/stdlib/js/src/kotlin/string.kt b/libraries/stdlib/js/src/kotlin/string.kt index 0915095951a..3da9cda83ea 100644 --- a/libraries/stdlib/js/src/kotlin/string.kt +++ b/libraries/stdlib/js/src/kotlin/string.kt @@ -7,6 +7,24 @@ package kotlin.text import kotlin.js.RegExp +/** + * Converts the characters in the specified array to a string. + */ +@SinceKotlin("1.2") +@kotlin.internal.InlineOnly +public actual inline fun String(chars: CharArray): String { + return js("String.fromCharCode").apply(null, chars) +} + +/** + * Converts the characters from a portion of the specified array to a string. + */ +@SinceKotlin("1.2") +public actual fun String(chars: CharArray, offset: Int, length: Int): String { + return String(chars.copyOfRange(offset, offset + length)) +} + + @kotlin.internal.InlineOnly public actual inline fun String.toUpperCase(): String = asDynamic().toUpperCase() diff --git a/libraries/stdlib/jvm/src/kotlin/text/StringsJVM.kt b/libraries/stdlib/jvm/src/kotlin/text/StringsJVM.kt index fe22b774faa..ba001a0e4ca 100644 --- a/libraries/stdlib/jvm/src/kotlin/text/StringsJVM.kt +++ b/libraries/stdlib/jvm/src/kotlin/text/StringsJVM.kt @@ -260,14 +260,14 @@ public inline fun String(bytes: ByteArray): String = * Converts the characters in the specified array to a string. */ @kotlin.internal.InlineOnly -public inline fun String(chars: CharArray): String = +public actual 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 = +public actual inline fun String(chars: CharArray, offset: Int, length: Int): String = java.lang.String(chars, offset, length) as String /** diff --git a/libraries/stdlib/test/text/StringTest.kt b/libraries/stdlib/test/text/StringTest.kt index eed3c8e9256..a56bf0b9f82 100644 --- a/libraries/stdlib/test/text/StringTest.kt +++ b/libraries/stdlib/test/text/StringTest.kt @@ -43,6 +43,28 @@ fun Char.isAsciiUpperCase() = this in 'A'..'Z' class StringTest { + @Test fun stringFromCharArrayFullSlice() { + val chars: CharArray = charArrayOf('K', 'o', 't', 'l', 'i', 'n') + assertEquals("Kotlin", String(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)) + } + + @Test fun stringFromCharArray() { + val chars: CharArray = charArrayOf('K', 'o', 't', 'l', 'i', 'n') + assertEquals("Kotlin", String(chars)) + } + + @Test fun stringFromCharArrayUnicodeSurrogatePairs() { + val chars: CharArray = charArrayOf('Ц', '月', '語', '\u016C', '\u138D', '\uD83C', '\uDC3A') + assertEquals("Ц月語Ŭᎍ🀺", String(chars)) + assertEquals("月", String(chars, 1, 1)) + assertEquals("Ŭᎍ🀺", String(chars, 3, 4)) + } + @Test fun isEmptyAndBlank() = withOneCharSequenceArg { arg1 -> class Case(val value: String?, val isNull: Boolean = false, val isEmpty: Boolean = false, val isBlank: Boolean = false)