Unify Regex.split behavior in JVM, JS regarding empty match delimiters

Rewrite split implementation for JVM

#KT-21049
This commit is contained in:
Ilya Gorbunov
2018-08-08 19:28:12 +03:00
parent 85af1f5d38
commit 5412227380
2 changed files with 35 additions and 1 deletions
@@ -187,7 +187,23 @@ internal constructor(private val nativePattern: Pattern) : Serializable {
@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
public actual 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()
val matcher = nativePattern.matcher(input)
if (!matcher.find() || limit == 1) return listOf(input.toString())
val result = ArrayList<String>(if (limit > 0) limit.coerceAtMost(10) else 10)
var lastStart = 0
val lastSplit = limit - 1 // negative if there's no limit
do {
result.add(input.substring(lastStart, matcher.start()))
lastStart = matcher.end()
if (lastSplit >= 0 && result.size == lastSplit) break
} while (matcher.find())
result.add(input.substring(lastStart, input.length))
return result
}
/** Returns the string representation of this regular expression, namely the [pattern] of this regular expression. */
+18
View File
@@ -203,6 +203,24 @@ class RegexTest {
}
@Test fun splitByEmptyMatch() {
val input = "test"
val emptyMatch = "".toRegex()
assertEquals(input.split(""), input.split(emptyMatch))
assertEquals(input.split("", limit = 3), input.split(emptyMatch, limit = 3))
assertEquals("".split(""), "".split(emptyMatch))
val emptyMatchBeforeT = "(?=t)".toRegex()
assertEquals(listOf("", "tes", "t"), input.split(emptyMatchBeforeT))
assertEquals(listOf("", "test"), input.split(emptyMatchBeforeT, limit = 2))
assertEquals(listOf("", "tee"), "tee".split(emptyMatchBeforeT))
}
}