Trimming and padding methods.
Kinda breaking change: Char.isWhitespace treats non-breaking spaces as whitespace too to match the Unicode definition of whitespace.
This commit is contained in:
@@ -59,9 +59,10 @@ deprecated("Please use Char.isJavaIdentifierPart() instead")
|
|||||||
public fun Char.isJavaLetterOrDigit(): Boolean = Character.isJavaLetterOrDigit(this)
|
public fun Char.isJavaLetterOrDigit(): Boolean = Character.isJavaLetterOrDigit(this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Determines whether a character is whitespace according to the Unicode standard.
|
||||||
* Returns `true` if the character is whitespace.
|
* Returns `true` if the character is whitespace.
|
||||||
*/
|
*/
|
||||||
public fun Char.isWhitespace(): Boolean = Character.isWhitespace(this)
|
public fun Char.isWhitespace(): Boolean = Character.isWhitespace(this) || Character.isSpaceChar(this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns `true` if this character is upper case.
|
* Returns `true` if this character is upper case.
|
||||||
|
|||||||
@@ -6,6 +6,56 @@ public fun String.trim(text: String): String = trimLeading(text).trimTrailing(te
|
|||||||
/** Returns the string with the prefix and postfix text trimmed */
|
/** Returns the string with the prefix and postfix text trimmed */
|
||||||
public fun String.trim(prefix: String, postfix: String): String = trimLeading(prefix).trimTrailing(postfix)
|
public fun String.trim(prefix: String, postfix: String): String = trimLeading(prefix).trimTrailing(postfix)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string with leading and trailing characters matching the [predicate] trimmed.
|
||||||
|
*/
|
||||||
|
inline public fun String.trim(predicate: (Char) -> Boolean): String {
|
||||||
|
val indices = this.indices
|
||||||
|
for (startIndex in indices)
|
||||||
|
if (!predicate(this[startIndex]))
|
||||||
|
for (endIndex in indices.reversed())
|
||||||
|
if (!predicate(this[endIndex]))
|
||||||
|
return substring(startIndex, endIndex + 1)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string with leading characters matching the [predicate] trimmed.
|
||||||
|
*/
|
||||||
|
inline public fun String.trimLeading(predicate: (Char) -> Boolean): String {
|
||||||
|
for (index in this.indices)
|
||||||
|
if (!predicate(this[index]))
|
||||||
|
return substring(index)
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string with trailing characters matching the [predicate] trimmed.
|
||||||
|
*/
|
||||||
|
inline public fun String.trimTrailing(predicate: (Char) -> Boolean): String {
|
||||||
|
for (index in this.indices.reversed())
|
||||||
|
if (!predicate(this[index]))
|
||||||
|
return substring(0, index + 1)
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string with leading and trailing characters in the [chars] array trimmed.
|
||||||
|
*/
|
||||||
|
public fun String.trim(vararg chars: Char): String = trim { it in chars }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string with leading and trailing characters in the [chars] array trimmed.
|
||||||
|
*/
|
||||||
|
public fun String.trimLeading(vararg chars: Char): String = trimLeading { it in chars }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string with trailing characters in the [chars] array trimmed.
|
||||||
|
*/
|
||||||
|
public fun String.trimTrailing(vararg chars: Char): String = trimTrailing { it in chars }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this string starts with the given [prefix], returns a copy of this string
|
* If this string starts with the given [prefix], returns a copy of this string
|
||||||
* with the prefix removed. Otherwise, returns this string.
|
* with the prefix removed. Otherwise, returns this string.
|
||||||
@@ -31,27 +81,56 @@ public fun String.trimTrailing(postfix: String): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a copy of this String with leading whitespace removed.
|
* Returns a string with leading and trailing whitespace trimmed.
|
||||||
*/
|
*/
|
||||||
public fun String.trimLeading(): String {
|
public fun String.trim(): String = trim { it.isWhitespace() }
|
||||||
var count = 0
|
|
||||||
|
|
||||||
while ((count < this.length) && (this[count] <= ' ')) {
|
/**
|
||||||
count++
|
* Returns a string with leading whitespace removed.
|
||||||
}
|
*/
|
||||||
return if (count > 0) substring(count) else this
|
public fun String.trimLeading(): String = trimLeading { it.isWhitespace() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string with trailing whitespace removed.
|
||||||
|
*/
|
||||||
|
public fun String.trimTrailing(): String = trimTrailing { it.isWhitespace() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Left pad a String with a specified character or space.
|
||||||
|
*
|
||||||
|
* @param length the desired string length.
|
||||||
|
* @param padChar the character to pad string with, if it has length less than the [length] specified. Space is used by default.
|
||||||
|
*/
|
||||||
|
public fun String.padLeft(length: Int, padChar: Char = ' '): String {
|
||||||
|
if (length < 0)
|
||||||
|
throw IllegalArgumentException("String length $length is less than zero.")
|
||||||
|
if (length <= this.length())
|
||||||
|
return this
|
||||||
|
|
||||||
|
val sb = StringBuilder(length)
|
||||||
|
for (i in 1..(length - this.length()))
|
||||||
|
sb.append(padChar)
|
||||||
|
sb.append(this)
|
||||||
|
return sb.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a copy of this String with trailing whitespace removed.
|
* Right pad a String with a specified character or space.
|
||||||
|
*
|
||||||
|
* @param length the desired string length.
|
||||||
|
* @param padChar the character to pad string with, if it has length less than the [length] specified. Space is used by default.
|
||||||
*/
|
*/
|
||||||
public fun String.trimTrailing(): String {
|
public fun String.padRight(length: Int, padChar: Char = ' '): String {
|
||||||
var count = this.length
|
if (length < 0)
|
||||||
|
throw IllegalArgumentException("String length $length is less than zero.")
|
||||||
|
if (length <= this.length())
|
||||||
|
return this
|
||||||
|
|
||||||
while (count > 0 && this[count - 1] <= ' ') {
|
val sb = StringBuilder(length)
|
||||||
count--
|
sb.append(this)
|
||||||
}
|
for (i in 1..(length - this.length()))
|
||||||
return if (count < this.length) substring(0, count) else this
|
sb.append(padChar)
|
||||||
|
return sb.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if the string is not null and not empty */
|
/** Returns true if the string is not null and not empty */
|
||||||
|
|||||||
@@ -48,11 +48,6 @@ public fun String.replace(oldChar: Char, newChar: Char): String = (this as java.
|
|||||||
*/
|
*/
|
||||||
public fun String.replaceAll(regex: String, replacement: String): String = (this as java.lang.String).replaceAll(regex, replacement)
|
public fun String.replaceAll(regex: String, replacement: String): String = (this as java.lang.String).replaceAll(regex, replacement)
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a copy of this string with leading and trailing whitespace trimmed.
|
|
||||||
*/
|
|
||||||
public fun String.trim(): String = (this as java.lang.String).trim()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a copy of this string converted to upper case using the rules of the default locale.
|
* Returns a copy of this string converted to upper case using the rules of the default locale.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -143,11 +143,15 @@ class StringTest {
|
|||||||
assertEquals("a ", " a ".trimLeading())
|
assertEquals("a ", " a ".trimLeading())
|
||||||
assertEquals("a b", " a b".trimLeading())
|
assertEquals("a b", " a b".trimLeading())
|
||||||
assertEquals("a b ", " a b ".trimLeading())
|
assertEquals("a b ", " a b ".trimLeading())
|
||||||
|
assertEquals("a", " \u00A0 a".trimLeading())
|
||||||
|
|
||||||
assertEquals("a", "\ta".trimLeading())
|
assertEquals("a", "\ta".trimLeading())
|
||||||
assertEquals("a", "\t\ta".trimLeading())
|
assertEquals("a", "\t\ta".trimLeading())
|
||||||
assertEquals("a", "\ra".trimLeading())
|
assertEquals("a", "\ra".trimLeading())
|
||||||
assertEquals("a", "\na".trimLeading())
|
assertEquals("a", "\na".trimLeading())
|
||||||
|
|
||||||
|
assertEquals("a=", "-=-=a=".trimLeading('-','='))
|
||||||
|
assertEquals("123a", "ab123a".trimLeading { !it.isDigit() })
|
||||||
}
|
}
|
||||||
|
|
||||||
test fun trimTrailing() {
|
test fun trimTrailing() {
|
||||||
@@ -158,11 +162,15 @@ class StringTest {
|
|||||||
assertEquals(" a", " a ".trimTrailing())
|
assertEquals(" a", " a ".trimTrailing())
|
||||||
assertEquals("a b", "a b ".trimTrailing())
|
assertEquals("a b", "a b ".trimTrailing())
|
||||||
assertEquals(" a b", " a b ".trimTrailing())
|
assertEquals(" a b", " a b ".trimTrailing())
|
||||||
|
assertEquals("a", "a \u00A0 ".trimTrailing())
|
||||||
|
|
||||||
assertEquals("a", "a\t".trimTrailing())
|
assertEquals("a", "a\t".trimTrailing())
|
||||||
assertEquals("a", "a\t\t".trimTrailing())
|
assertEquals("a", "a\t\t".trimTrailing())
|
||||||
assertEquals("a", "a\r".trimTrailing())
|
assertEquals("a", "a\r".trimTrailing())
|
||||||
assertEquals("a", "a\n".trimTrailing())
|
assertEquals("a", "a\n".trimTrailing())
|
||||||
|
|
||||||
|
assertEquals("=a", "=a=-=-".trimTrailing('-','='))
|
||||||
|
assertEquals("ab123", "ab123a".trimTrailing { !it.isDigit() })
|
||||||
}
|
}
|
||||||
|
|
||||||
test fun trimTrailingAndLeading() {
|
test fun trimTrailingAndLeading() {
|
||||||
@@ -174,12 +182,46 @@ class StringTest {
|
|||||||
"\ta\tb\t",
|
"\ta\tb\t",
|
||||||
"\t\ta\t\t",
|
"\t\ta\t\t",
|
||||||
"\ra\r",
|
"\ra\r",
|
||||||
"\na\n"
|
"\na\n",
|
||||||
|
" \u00A0 a \u00A0 "
|
||||||
)
|
)
|
||||||
|
|
||||||
for (example in examples) {
|
for (example in examples) {
|
||||||
assertEquals(example.trim(), example.trimTrailing().trimLeading())
|
assertEquals(example.trim(), example.trimTrailing().trimLeading())
|
||||||
assertEquals(example.trim(), example.trimLeading().trimTrailing())
|
assertEquals(example.trim(), example.trimLeading().trimTrailing())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val examplesForPredicate = array(
|
||||||
|
"123",
|
||||||
|
"-=123=-"
|
||||||
|
)
|
||||||
|
|
||||||
|
val trimChars = charArray('-','=')
|
||||||
|
val trimPredicate = { (it: Char) -> !it.isDigit() }
|
||||||
|
for (example in examplesForPredicate) {
|
||||||
|
assertEquals(example.trimLeading(*trimChars).trimTrailing(*trimChars), example.trim(*trimChars))
|
||||||
|
assertEquals(example.trimLeading(trimPredicate).trimTrailing(trimPredicate), example.trim(trimPredicate))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test fun padLeft() {
|
||||||
|
assertEquals("s", "s".padLeft(0))
|
||||||
|
assertEquals("s", "s".padLeft(1))
|
||||||
|
assertEquals(" ", "".padLeft(2))
|
||||||
|
assertEquals("--s", "s".padLeft(3, '-'))
|
||||||
|
fails {
|
||||||
|
"s".padLeft(-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test fun padRight() {
|
||||||
|
assertEquals("s", "s".padRight(0))
|
||||||
|
assertEquals("s", "s".padRight(1))
|
||||||
|
assertEquals(" ", "".padRight(2))
|
||||||
|
assertEquals("s--", "s".padRight(3, '-'))
|
||||||
|
fails {
|
||||||
|
"s".padRight(-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user