Use regex for case-insensitive String.replace
KT-41799
This commit is contained in:
@@ -77,27 +77,36 @@ public actual fun String.replace(oldChar: Char, newChar: Char, ignoreCase: Boole
|
|||||||
*/
|
*/
|
||||||
@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
|
@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
|
||||||
public actual fun String.replace(oldValue: String, newValue: String, ignoreCase: Boolean = false): String {
|
public actual fun String.replace(oldValue: String, newValue: String, ignoreCase: Boolean = false): String {
|
||||||
// prefer case-insensitive platform implementation
|
if (ignoreCase) {
|
||||||
if (!ignoreCase) return (this as java.lang.String).replace(oldValue, newValue)
|
val matcher = Pattern.compile(oldValue, Pattern.LITERAL or Pattern.CASE_INSENSITIVE).matcher(this)
|
||||||
|
if (!matcher.find()) return this
|
||||||
|
val stringBuilder = StringBuilder()
|
||||||
|
var i = 0
|
||||||
|
do {
|
||||||
|
stringBuilder.append(this, i, matcher.start()).append(newValue)
|
||||||
|
i = matcher.end()
|
||||||
|
} while (matcher.find())
|
||||||
|
return stringBuilder.append(this, i, length).toString()
|
||||||
|
} else {
|
||||||
|
var occurrenceIndex: Int = indexOf(oldValue, 0, ignoreCase)
|
||||||
|
// FAST PATH: no match
|
||||||
|
if (occurrenceIndex < 0) return this
|
||||||
|
|
||||||
var occurrenceIndex: Int = indexOf(oldValue, 0, ignoreCase)
|
val oldValueLength = oldValue.length
|
||||||
// FAST PATH: no match
|
val searchStep = oldValueLength.coerceAtLeast(1)
|
||||||
if (occurrenceIndex < 0) return this
|
val newLengthHint = length - oldValueLength + newValue.length
|
||||||
|
if (newLengthHint < 0) throw OutOfMemoryError()
|
||||||
|
val stringBuilder = StringBuilder(newLengthHint)
|
||||||
|
|
||||||
val oldValueLength = oldValue.length
|
var i = 0
|
||||||
val searchStep = oldValueLength.coerceAtLeast(1)
|
do {
|
||||||
val newLengthHint = length - oldValueLength + newValue.length
|
stringBuilder.append(this, i, occurrenceIndex).append(newValue)
|
||||||
if (newLengthHint < 0) throw OutOfMemoryError()
|
i = occurrenceIndex + oldValueLength
|
||||||
val stringBuilder = StringBuilder(newLengthHint)
|
if (occurrenceIndex >= length) break
|
||||||
|
occurrenceIndex = indexOf(oldValue, occurrenceIndex + searchStep, ignoreCase)
|
||||||
var i = 0
|
} while (occurrenceIndex > 0)
|
||||||
do {
|
return stringBuilder.append(this, i, length).toString()
|
||||||
stringBuilder.append(this, i, occurrenceIndex).append(newValue)
|
}
|
||||||
i = occurrenceIndex + oldValueLength
|
|
||||||
if (occurrenceIndex >= length) break
|
|
||||||
occurrenceIndex = indexOf(oldValue, occurrenceIndex + searchStep, ignoreCase)
|
|
||||||
} while (occurrenceIndex > 0)
|
|
||||||
return stringBuilder.append(this, i, length).toString()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -895,6 +895,7 @@ class StringTest {
|
|||||||
assertEquals("/b/", input.replace("ab", "/", ignoreCase = true))
|
assertEquals("/b/", input.replace("ab", "/", ignoreCase = true))
|
||||||
|
|
||||||
assertEquals("-a-b-b-A-b-", input.replace("", "-"))
|
assertEquals("-a-b-b-A-b-", input.replace("", "-"))
|
||||||
|
assertEquals("-a-b-b-A-b-", input.replace("", "-", ignoreCase = true))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun replaceFirst() {
|
@Test fun replaceFirst() {
|
||||||
|
|||||||
Reference in New Issue
Block a user