Use CharSequence in split, splitToSequence, lines
This commit is contained in:
@@ -873,11 +873,11 @@ public operator fun CharSequence.contains(regex: Regex): Boolean = regex.contain
|
|||||||
// rangesDelimitedBy
|
// rangesDelimitedBy
|
||||||
|
|
||||||
|
|
||||||
private class DelimitedRangesSequence(private val string: String, private val startIndex: Int, private val limit: Int, private val getNextMatch: String.(Int) -> Pair<Int, Int>?): Sequence<IntRange> {
|
private class DelimitedRangesSequence(private val input: CharSequence, private val startIndex: Int, private val limit: Int, private val getNextMatch: CharSequence.(Int) -> Pair<Int, Int>?): Sequence<IntRange> {
|
||||||
|
|
||||||
override fun iterator(): Iterator<IntRange> = object : Iterator<IntRange> {
|
override fun iterator(): Iterator<IntRange> = object : Iterator<IntRange> {
|
||||||
var nextState: Int = -1 // -1 for unknown, 0 for done, 1 for continue
|
var nextState: Int = -1 // -1 for unknown, 0 for done, 1 for continue
|
||||||
var currentStartIndex: Int = Math.min(Math.max(startIndex, 0), string.length())
|
var currentStartIndex: Int = Math.min(Math.max(startIndex, 0), input.length())
|
||||||
var nextSearchIndex: Int = currentStartIndex
|
var nextSearchIndex: Int = currentStartIndex
|
||||||
var nextItem: IntRange? = null
|
var nextItem: IntRange? = null
|
||||||
var counter: Int = 0
|
var counter: Int = 0
|
||||||
@@ -888,14 +888,14 @@ private class DelimitedRangesSequence(private val string: String, private val st
|
|||||||
nextItem = null
|
nextItem = null
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (limit > 0 && ++counter >= limit || nextSearchIndex > string.length()) {
|
if (limit > 0 && ++counter >= limit || nextSearchIndex > input.length()) {
|
||||||
nextItem = currentStartIndex..string.lastIndex
|
nextItem = currentStartIndex..input.lastIndex
|
||||||
nextSearchIndex = -1
|
nextSearchIndex = -1
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val match = string.getNextMatch(nextSearchIndex)
|
val match = input.getNextMatch(nextSearchIndex)
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
nextItem = currentStartIndex..string.lastIndex
|
nextItem = currentStartIndex..input.lastIndex
|
||||||
nextSearchIndex = -1
|
nextSearchIndex = -1
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -939,7 +939,7 @@ private class DelimitedRangesSequence(private val string: String, private val st
|
|||||||
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
|
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
|
||||||
* @param limit The maximum number of substrings to return. Zero by default means no limit is set.
|
* @param limit The maximum number of substrings to return. Zero by default means no limit is set.
|
||||||
*/
|
*/
|
||||||
private fun String.rangesDelimitedBy(vararg delimiters: Char, startIndex: Int = 0, ignoreCase: Boolean = false, limit: Int = 0): Sequence<IntRange> {
|
private fun CharSequence.rangesDelimitedBy(delimiters: CharArray, startIndex: Int = 0, ignoreCase: Boolean = false, limit: Int = 0): Sequence<IntRange> {
|
||||||
require(limit >= 0, { "Limit must be non-negative, but was $limit" })
|
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 -> findAnyOf(delimiters, startIndex, ignoreCase = ignoreCase, last = false)?.let { it.first to 1 } })
|
||||||
@@ -960,7 +960,7 @@ private fun String.rangesDelimitedBy(vararg delimiters: Char, startIndex: Int =
|
|||||||
* the beginning to the end of this string, and finds at each position the first element in [delimiters]
|
* the beginning to the end of this string, and finds at each position the first element in [delimiters]
|
||||||
* that matches this string at that position.
|
* that matches this string at that position.
|
||||||
*/
|
*/
|
||||||
private fun String.rangesDelimitedBy(vararg delimiters: String, startIndex: Int = 0, ignoreCase: Boolean = false, limit: Int = 0): Sequence<IntRange> {
|
private fun CharSequence.rangesDelimitedBy(delimiters: Array<out String>, startIndex: Int = 0, ignoreCase: Boolean = false, limit: Int = 0): Sequence<IntRange> {
|
||||||
require(limit >= 0, { "Limit must be non-negative, but was $limit" } )
|
require(limit >= 0, { "Limit must be non-negative, but was $limit" } )
|
||||||
val delimitersList = delimiters.asList()
|
val delimitersList = delimiters.asList()
|
||||||
|
|
||||||
@@ -982,8 +982,8 @@ private fun String.rangesDelimitedBy(vararg delimiters: String, startIndex: Int
|
|||||||
* the beginning to the end of this string, and finds at each position the first element in [delimiters]
|
* the beginning to the end of this string, and finds at each position the first element in [delimiters]
|
||||||
* that matches this string at that position.
|
* that matches this string at that position.
|
||||||
*/
|
*/
|
||||||
public fun String.splitToSequence(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): Sequence<String> =
|
public fun CharSequence.splitToSequence(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): Sequence<String> =
|
||||||
rangesDelimitedBy(*delimiters, ignoreCase = ignoreCase, limit = limit) map { substring(it) }
|
rangesDelimitedBy(delimiters, ignoreCase = ignoreCase, limit = limit).map { substring(it) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits this string to a list of strings around occurrences of the specified [delimiters].
|
* Splits this string to a list of strings around occurrences of the specified [delimiters].
|
||||||
@@ -996,8 +996,8 @@ public fun String.splitToSequence(vararg delimiters: String, ignoreCase: Boolean
|
|||||||
* the beginning to the end of this string, and matches at each position the first element in [delimiters]
|
* the beginning to the end of this string, and matches at each position the first element in [delimiters]
|
||||||
* that is equal to a delimiter in this instance at that position.
|
* that is equal to a delimiter in this instance at that position.
|
||||||
*/
|
*/
|
||||||
public fun String.split(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): List<String> =
|
public fun CharSequence.split(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): List<String> =
|
||||||
splitToSequence(*delimiters, ignoreCase = ignoreCase, limit = limit).toList()
|
rangesDelimitedBy(delimiters, ignoreCase = ignoreCase, limit = limit).asIterable().map { substring(it) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits this string to a sequence of strings around occurrences of the specified [delimiters].
|
* Splits this string to a sequence of strings around occurrences of the specified [delimiters].
|
||||||
@@ -1006,8 +1006,8 @@ public fun String.split(vararg delimiters: String, ignoreCase: Boolean = false,
|
|||||||
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
|
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
|
||||||
* @param limit The maximum number of substrings to return.
|
* @param limit The maximum number of substrings to return.
|
||||||
*/
|
*/
|
||||||
public fun String.splitToSequence(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): Sequence<String> =
|
public fun CharSequence.splitToSequence(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): Sequence<String> =
|
||||||
rangesDelimitedBy(*delimiters, ignoreCase = ignoreCase, limit = limit) map { substring(it) }
|
rangesDelimitedBy(delimiters, ignoreCase = ignoreCase, limit = limit).map { substring(it) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits this string to a list of strings around occurrences of the specified [delimiters].
|
* Splits this string to a list of strings around occurrences of the specified [delimiters].
|
||||||
@@ -1016,8 +1016,8 @@ public fun String.splitToSequence(vararg delimiters: Char, ignoreCase: Boolean =
|
|||||||
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
|
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
|
||||||
* @param limit The maximum number of substrings to return.
|
* @param limit The maximum number of substrings to return.
|
||||||
*/
|
*/
|
||||||
public fun String.split(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): List<String> =
|
public fun CharSequence.split(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): List<String> =
|
||||||
splitToSequence(*delimiters, ignoreCase = ignoreCase, limit = limit).toList()
|
rangesDelimitedBy(delimiters, ignoreCase = ignoreCase, limit = limit).asIterable().map { substring(it) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits this string around matches of the given regular expression.
|
* Splits this string around matches of the given regular expression.
|
||||||
@@ -1025,14 +1025,14 @@ public fun String.split(vararg delimiters: Char, ignoreCase: Boolean = false, li
|
|||||||
* @param limit Non-negative value specifying the maximum number of substrings to return.
|
* @param limit Non-negative value specifying the maximum number of substrings to return.
|
||||||
* Zero by default means no limit is set.
|
* Zero by default means no limit is set.
|
||||||
*/
|
*/
|
||||||
public fun String.split(pattern: Regex, limit: Int = 0): List<String> = pattern.split(this, limit)
|
public fun CharSequence.split(pattern: Regex, limit: Int = 0): List<String> = pattern.split(this, limit)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits this string to a sequence of lines delimited by any of the following character sequences: CRLF, LF or CR.
|
* Splits this string to a sequence of lines delimited by any of the following character sequences: CRLF, LF or CR.
|
||||||
*/
|
*/
|
||||||
public fun String.lineSequence(): Sequence<String> = splitToSequence("\r\n", "\n", "\r")
|
public fun CharSequence.lineSequence(): Sequence<String> = splitToSequence("\r\n", "\n", "\r")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * Splits this string to a list of lines delimited by any of the following character sequences: CRLF, LF or CR.
|
* * Splits this string to a list of lines delimited by any of the following character sequences: CRLF, LF or CR.
|
||||||
*/
|
*/
|
||||||
public fun String.lines(): List<String> = lineSequence().toList()
|
public fun CharSequence.lines(): List<String> = lineSequence().toList()
|
||||||
|
|||||||
@@ -670,104 +670,6 @@ public operator fun String.contains(char: Char, ignoreCase: Boolean = false): Bo
|
|||||||
indexOf(char, ignoreCase = ignoreCase) >= 0
|
indexOf(char, ignoreCase = ignoreCase) >= 0
|
||||||
|
|
||||||
|
|
||||||
// rangesDelimitedBy
|
|
||||||
|
|
||||||
/*
|
|
||||||
private class DelimitedRangesSequence(private val string: String, private val startIndex: Int, private val limit: Int, private val getNextMatch: String.(Int) -> Pair<Int, Int>?): Sequence<IntRange> {
|
|
||||||
|
|
||||||
override fun iterator(): Iterator<IntRange> = object : Iterator<IntRange> {
|
|
||||||
var nextState: Int = -1 // -1 for unknown, 0 for done, 1 for continue
|
|
||||||
var currentStartIndex: Int = Math.min(Math.max(startIndex, 0), string.length())
|
|
||||||
var nextSearchIndex: Int = currentStartIndex
|
|
||||||
var nextItem: IntRange? = null
|
|
||||||
var counter: Int = 0
|
|
||||||
|
|
||||||
private fun calcNext() {
|
|
||||||
if (nextSearchIndex < 0) {
|
|
||||||
nextState = 0
|
|
||||||
nextItem = null
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (limit > 0 && ++counter >= limit || nextSearchIndex > string.length()) {
|
|
||||||
nextItem = currentStartIndex..string.lastIndex
|
|
||||||
nextSearchIndex = -1
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
val match = string.getNextMatch(nextSearchIndex)
|
|
||||||
if (match == null) {
|
|
||||||
nextItem = currentStartIndex..string.lastIndex
|
|
||||||
nextSearchIndex = -1
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
val (index,length) = match
|
|
||||||
nextItem = currentStartIndex..index-1
|
|
||||||
currentStartIndex = index + length
|
|
||||||
nextSearchIndex = currentStartIndex + if (length == 0) 1 else 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nextState = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun next(): IntRange {
|
|
||||||
if (nextState == -1)
|
|
||||||
calcNext()
|
|
||||||
if (nextState == 0)
|
|
||||||
throw NoSuchElementException()
|
|
||||||
val result = nextItem as IntRange
|
|
||||||
// Clean next to avoid keeping reference on yielded instance
|
|
||||||
nextItem = null
|
|
||||||
nextState = -1
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hasNext(): Boolean {
|
|
||||||
if (nextState == -1)
|
|
||||||
calcNext()
|
|
||||||
return nextState == 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a sequence of index ranges of substrings in this string around occurrences of the specified [delimiters].
|
|
||||||
*
|
|
||||||
* @param delimiters One or more characters to be used as delimiters.
|
|
||||||
* @param startIndex The index to start searching delimiters from.
|
|
||||||
* No range having its start value less than [startIndex] is returned.
|
|
||||||
* [startIndex] is coerced to be non-negative and not greater than length of this string.
|
|
||||||
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
|
|
||||||
* @param limit The maximum number of substrings to return. Zero by default means no limit is set.
|
|
||||||
*/
|
|
||||||
private fun String.rangesDelimitedBy(vararg delimiters: Char, startIndex: Int = 0, ignoreCase: Boolean = false, limit: Int = 0): Sequence<IntRange> {
|
|
||||||
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 } })
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a sequence of index ranges of substrings in this string around occurrences of the specified [delimiters].
|
|
||||||
*
|
|
||||||
* @param delimiters One or more strings to be used as delimiters.
|
|
||||||
* @param startIndex The index to start searching delimiters from.
|
|
||||||
* No range having its start value less than [startIndex] is returned.
|
|
||||||
* [startIndex] is coerced to be non-negative and not greater than length of this string.
|
|
||||||
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
|
|
||||||
* @param limit The maximum number of substrings to return. Zero by default means no limit is set.
|
|
||||||
*
|
|
||||||
* To avoid ambiguous results when strings in [delimiters] have characters in common, this method proceeds from
|
|
||||||
* the beginning to the end of this string, and finds at each position the first element in [delimiters]
|
|
||||||
* that matches this string at that position.
|
|
||||||
*/
|
|
||||||
private fun String.rangesDelimitedBy(vararg delimiters: String, startIndex: Int = 0, ignoreCase: Boolean = false, limit: Int = 0): Sequence<IntRange> {
|
|
||||||
require(limit >= 0, { "Limit must be non-negative, but was $limit" } )
|
|
||||||
val delimitersList = delimiters.asList()
|
|
||||||
|
|
||||||
return DelimitedRangesSequence(this, startIndex, limit, { startIndex -> findAnyOf(delimitersList, startIndex, ignoreCase = ignoreCase, last = false)?.let { it.first to it.second.length ()} })
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// split
|
// split
|
||||||
@@ -783,8 +685,9 @@ private fun String.rangesDelimitedBy(vararg delimiters: String, startIndex: Int
|
|||||||
* the beginning to the end of this string, and finds at each position the first element in [delimiters]
|
* the beginning to the end of this string, and finds at each position the first element in [delimiters]
|
||||||
* that matches this string at that position.
|
* that matches this string at that position.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||||
public fun String.splitToSequence(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): Sequence<String> =
|
public fun String.splitToSequence(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): Sequence<String> =
|
||||||
rangesDelimitedBy(*delimiters, ignoreCase = ignoreCase, limit = limit) map { substring(it) }
|
splitToSequence(*delimiters, ignoreCase = ignoreCase, limit = limit)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits this string to a list of strings around occurrences of the specified [delimiters].
|
* Splits this string to a list of strings around occurrences of the specified [delimiters].
|
||||||
@@ -797,6 +700,7 @@ public fun String.splitToSequence(vararg delimiters: String, ignoreCase: Boolean
|
|||||||
* the beginning to the end of this string, and matches at each position the first element in [delimiters]
|
* the beginning to the end of this string, and matches at each position the first element in [delimiters]
|
||||||
* that is equal to a delimiter in this instance at that position.
|
* that is equal to a delimiter in this instance at that position.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||||
public fun String.split(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): List<String> =
|
public fun String.split(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): List<String> =
|
||||||
splitToSequence(*delimiters, ignoreCase = ignoreCase, limit = limit).toList()
|
splitToSequence(*delimiters, ignoreCase = ignoreCase, limit = limit).toList()
|
||||||
|
|
||||||
@@ -807,8 +711,9 @@ public fun String.split(vararg delimiters: String, ignoreCase: Boolean = false,
|
|||||||
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
|
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
|
||||||
* @param limit The maximum number of substrings to return.
|
* @param limit The maximum number of substrings to return.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||||
public fun String.splitToSequence(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): Sequence<String> =
|
public fun String.splitToSequence(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): Sequence<String> =
|
||||||
rangesDelimitedBy(*delimiters, ignoreCase = ignoreCase, limit = limit) map { substring(it) }
|
splitToSequence(*delimiters, ignoreCase = ignoreCase, limit = limit)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits this string to a list of strings around occurrences of the specified [delimiters].
|
* Splits this string to a list of strings around occurrences of the specified [delimiters].
|
||||||
@@ -817,6 +722,7 @@ public fun String.splitToSequence(vararg delimiters: Char, ignoreCase: Boolean =
|
|||||||
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
|
* @param ignoreCase `true` to ignore character case when matching a delimiter. By default `false`.
|
||||||
* @param limit The maximum number of substrings to return.
|
* @param limit The maximum number of substrings to return.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||||
public fun String.split(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): List<String> =
|
public fun String.split(vararg delimiters: Char, ignoreCase: Boolean = false, limit: Int = 0): List<String> =
|
||||||
splitToSequence(*delimiters, ignoreCase = ignoreCase, limit = limit).toList()
|
splitToSequence(*delimiters, ignoreCase = ignoreCase, limit = limit).toList()
|
||||||
|
|
||||||
@@ -826,16 +732,18 @@ public fun String.split(vararg delimiters: Char, ignoreCase: Boolean = false, li
|
|||||||
* @param limit Non-negative value specifying the maximum number of substrings to return.
|
* @param limit Non-negative value specifying the maximum number of substrings to return.
|
||||||
* Zero by default means no limit is set.
|
* Zero by default means no limit is set.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||||
public fun String.split(pattern: Regex, limit: Int = 0): List<String> = pattern.split(this, limit)
|
public fun String.split(pattern: Regex, limit: Int = 0): List<String> = pattern.split(this, limit)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splits this string to a sequence of lines delimited by any of the following character sequences: CRLF, LF or CR.
|
* Splits this string to a sequence of lines delimited by any of the following character sequences: CRLF, LF or CR.
|
||||||
*/
|
*/
|
||||||
public fun String.lineSequence(): Sequence<String> = splitToSequence("\r\n", "\n", "\r")
|
@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||||
|
public fun String.lineSequence(): Sequence<String> = lineSequence()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * Splits this string to a list of lines delimited by any of the following character sequences: CRLF, LF or CR.
|
* * Splits this string to a list of lines delimited by any of the following character sequences: CRLF, LF or CR.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Provided for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||||
public fun String.lines(): List<String> = lineSequence().toList()
|
public fun String.lines(): List<String> = lineSequence().toList()
|
||||||
|
|
||||||
*/
|
|
||||||
|
|||||||
Reference in New Issue
Block a user