diff --git a/js/js.libraries/src/core/stringsCode.kt b/js/js.libraries/src/core/stringsCode.kt index eec69707aaa..0007091bedb 100644 --- a/js/js.libraries/src/core/stringsCode.kt +++ b/js/js.libraries/src/core/stringsCode.kt @@ -75,6 +75,27 @@ public inline fun String.decapitalize(): String { return if (isNotEmpty()) substring(0, 1).toLowerCase() + substring(1) else this } +/** + * Returns a string containing this char sequence repeated [n] times. + * @throws [IllegalArgumentException] when n < 0. + */ +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 -> { + var result = "" + if (!isEmpty()) { + val s = this.toString() + for (i in 1..n) { + result += s + } + } + return result + } + } +} public fun String.replace(oldValue: String, newValue: String, ignoreCase: Boolean = false): String = nativeReplace(RegExp(Regex.escape(oldValue), if (ignoreCase) "gi" else "g"), Regex.escapeReplacement(newValue)) diff --git a/libraries/stdlib/src/kotlin/text/StringsJVM.kt b/libraries/stdlib/src/kotlin/text/StringsJVM.kt index e4b2809a525..bbbb9bc783b 100644 --- a/libraries/stdlib/src/kotlin/text/StringsJVM.kt +++ b/libraries/stdlib/src/kotlin/text/StringsJVM.kt @@ -457,14 +457,25 @@ public fun String.decapitalize(): String { * @sample test.text.StringJVMTest.repeat */ public fun CharSequence.repeat(n: Int): String { - if (n < 0) - throw IllegalArgumentException("Value should be non-negative, but was $n") + require (n >= 0) { "Count 'n' must be non-negative, but was $n." } - val sb = StringBuilder(n * length) - for (i in 1..n) { - sb.append(this) + 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() + } + } + } } - return sb.toString() } diff --git a/libraries/stdlib/test/text/StringJVMTest.kt b/libraries/stdlib/test/text/StringJVMTest.kt index 157773ae1a8..19fd45660c6 100644 --- a/libraries/stdlib/test/text/StringJVMTest.kt +++ b/libraries/stdlib/test/text/StringJVMTest.kt @@ -45,17 +45,6 @@ class StringJVMTest { } } - @test fun repeat() = withOneCharSequenceArg { arg1 -> - fun String.repeat(n: Int): String = arg1(this).repeat(n) - - assertFails { "foo".repeat(-1) } - assertEquals("", "foo".repeat(0)) - assertEquals("foo", "foo".repeat(1)) - assertEquals("foofoo", "foo".repeat(2)) - assertEquals("foofoofoo", "foo".repeat(3)) - } - - @test fun sliceCharSequenceFails() = withOneCharSequenceArg { arg1 -> assertFails { arg1("abc").slice(1..4) diff --git a/libraries/stdlib/test/text/StringTest.kt b/libraries/stdlib/test/text/StringTest.kt index d52e5b94711..e5fa02b5467 100644 --- a/libraries/stdlib/test/text/StringTest.kt +++ b/libraries/stdlib/test/text/StringTest.kt @@ -334,6 +334,19 @@ class StringTest { assertEquals("xxx", s.replaceBeforeLast("=", "/new/path", "xxx")) } + @test fun repeat() = withOneCharSequenceArg { arg1 -> + fun String.repeat(n: Int): String = arg1(this).repeat(n) + + assertFails { "foo".repeat(-1) } + assertEquals("", "foo".repeat(0)) + assertEquals("foo", "foo".repeat(1)) + assertEquals("foofoo", "foo".repeat(2)) + assertEquals("foofoofoo", "foo".repeat(3)) + + assertEquals("", "".repeat(Int.MAX_VALUE)) + assertEquals("aaaaaaaaaaaaa", "a".repeat(13)) + } + @test fun stringIterator() = withOneCharSequenceArg("239") { data -> var sum = 0 for(c in data)