From 2da9f12bc535954f4a4aa6b7acdbe3aae7d6e1ef Mon Sep 17 00:00:00 2001 From: Ilya Gorbunov Date: Tue, 23 Jan 2018 21:24:27 +0300 Subject: [PATCH] Inline findAnyOf(chars) into indexOfAny/lastIndexOfAny This helps to reduce allocation count #KT-22042 --- libraries/stdlib/src/kotlin/text/Strings.kt | 53 ++++++++++++--------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/libraries/stdlib/src/kotlin/text/Strings.kt b/libraries/stdlib/src/kotlin/text/Strings.kt index 196f77061d0..1bf7dc99bbb 100644 --- a/libraries/stdlib/src/kotlin/text/Strings.kt +++ b/libraries/stdlib/src/kotlin/text/Strings.kt @@ -800,24 +800,6 @@ public fun CharSequence.commonSuffixWith(other: CharSequence, ignoreCase: Boolea // indexOfAny() -private fun CharSequence.findAnyOf(chars: CharArray, startIndex: Int, ignoreCase: Boolean, last: Boolean): Pair? { - if (!ignoreCase && chars.size == 1 && this is String) { - val char = chars.single() - val index = if (!last) nativeIndexOf(char, startIndex) else nativeLastIndexOf(char, startIndex) - return if (index < 0) null else index to char - } - - val indices = if (!last) startIndex.coerceAtLeast(0)..lastIndex else startIndex.coerceAtMost(lastIndex) downTo 0 - for (index in indices) { - val charAtIndex = get(index) - val matchingCharIndex = chars.indexOfFirst { it.equals(charAtIndex, ignoreCase) } - if (matchingCharIndex >= 0) - return index to chars[matchingCharIndex] - } - - return null -} - /** * Finds the index of the first occurrence of any of the specified [chars] in this char sequence, * starting from the specified [startIndex] and optionally ignoring the case. @@ -826,8 +808,19 @@ private fun CharSequence.findAnyOf(chars: CharArray, startIndex: Int, ignoreCase * @returns An index of the first occurrence of matched character from [chars] or -1 if none of [chars] are found. * */ -public fun CharSequence.indexOfAny(chars: CharArray, startIndex: Int = 0, ignoreCase: Boolean = false): Int = - findAnyOf(chars, startIndex, ignoreCase, last = false)?.first ?: -1 +public fun CharSequence.indexOfAny(chars: CharArray, startIndex: Int = 0, ignoreCase: Boolean = false): Int { + if (!ignoreCase && chars.size == 1 && this is String) { + val char = chars.single() + return nativeIndexOf(char, startIndex) + } + + for (index in startIndex.coerceAtLeast(0)..lastIndex) { + val charAtIndex = get(index) + if (chars.any { it.equals(charAtIndex, ignoreCase) }) + return index + } + return -1 +} /** * Finds the index of the last occurrence of any of the specified [chars] in this char sequence, @@ -838,8 +831,21 @@ public fun CharSequence.indexOfAny(chars: CharArray, startIndex: Int = 0, ignore * @returns An index of the last occurrence of matched character from [chars] or -1 if none of [chars] are found. * */ -public fun CharSequence.lastIndexOfAny(chars: CharArray, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int = - findAnyOf(chars, startIndex, ignoreCase, last = true)?.first ?: -1 +public fun CharSequence.lastIndexOfAny(chars: CharArray, startIndex: Int = lastIndex, ignoreCase: Boolean = false): Int { + if (!ignoreCase && chars.size == 1 && this is String) { + val char = chars.single() + return nativeLastIndexOf(char, startIndex) + } + + + for (index in startIndex.coerceAtMost(lastIndex) downTo 0) { + val charAtIndex = get(index) + if (chars.any { it.equals(charAtIndex, ignoreCase) }) + return index + } + + return -1 +} private fun CharSequence.indexOf(other: CharSequence, startIndex: Int, endIndex: Int, ignoreCase: Boolean, last: Boolean = false): Int { @@ -1109,7 +1115,8 @@ private class DelimitedRangesSequence(private val input: CharSequence, private v private fun CharSequence.rangesDelimitedBy(delimiters: CharArray, startIndex: Int = 0, ignoreCase: Boolean = false, limit: Int = 0): Sequence { require(limit >= 0, { "Limit must be non-negative, but was $limit." }) - return DelimitedRangesSequence(this, startIndex, limit, { startIndex -> findAnyOf(delimiters, startIndex, ignoreCase = ignoreCase, last = false)?.let { it.first to 1 } }) + return DelimitedRangesSequence(this, startIndex, limit, { startIndex -> + indexOfAny(delimiters, startIndex, ignoreCase = ignoreCase).let { if (it < 0) null else it to 1 } }) }