diff options
author | Linnea Gräf <nea@nea.moe> | 2024-02-29 22:13:22 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-29 22:13:22 +0100 |
commit | d4bd14793bf920d27de14bcea7350d67f1a8a000 (patch) | |
tree | 1bf8b3e241448317e102302de6ced3815cb35bde /src/main/java/at | |
parent | 0c96b9d6ee14a9dcaafad303ed82357f252fdd6b (diff) | |
download | skyhanni-d4bd14793bf920d27de14bcea7350d67f1a8a000.tar.gz skyhanni-d4bd14793bf920d27de14bcea7350d67f1a8a000.tar.bz2 skyhanni-d4bd14793bf920d27de14bcea7350d67f1a8a000.zip |
Improve performance of removeColor. (#1079)
Diffstat (limited to 'src/main/java/at')
-rw-r--r-- | src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt index 192073111..a8ab6e6cd 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt @@ -34,7 +34,7 @@ object StringUtils { return first + lowercase.substring(1) } - private val formattingChars by lazy { "kmolnr".toCharArray() + "kmolnr".uppercase().toCharArray() } + private val formattingChars = "kmolnrKMOLNR".toSet() /** * Removes color and optionally formatting codes from the given string, leaving plain text. @@ -42,22 +42,53 @@ object StringUtils { * @param keepFormatting Boolean indicating whether to retain non-color formatting codes (default: false). * @return A string with color codes removed (and optionally formatting codes if specified). */ - fun String.removeColor(keepFormatting: Boolean = false): String { - val builder = StringBuilder(this.length) - - var counter = 0 - while (counter < this.length) { - if (this[counter] == '§') { - if (!keepFormatting || this[counter + 1] !in formattingChars) { - counter += 2 - continue - } + fun CharSequence.removeColor(keepFormatting: Boolean = false): String { + // Glossary: + // Formatting indicator: The '§' character indicating the beginning of a formatting sequence + // Formatting code: The character following a formatting indicator which specifies what color or text style this sequence corresponds to + // Formatting sequence: The combination of a formatting indicator and code that changes the color or format of a string + + // Find the first formatting indicator + var nextFormattingSequence = indexOf('§') + + // If this string does not contain any formatting indicators, just return this string directly + if (nextFormattingSequence < 0) return this.toString() + + // Let's create a new string, and pre-allocate enough space to store this entire string + val cleanedString = StringBuilder(this.length) + + // Read index stores the position in `this` which we have written up until now + // a/k/a where we need to start reading from + var readIndex = 0 + + // As long as there still is a formatting indicator left in our string + while (nextFormattingSequence >= 0) { + + // Write everything from the read index up to the next formatting indicator into our clean string + cleanedString.append(this, readIndex, nextFormattingSequence) + + // If the next formatting sequence's code indicates a non-color format and we should keep those + if (keepFormatting && nextFormattingSequence + 1 < length && this[nextFormattingSequence + 1] in formattingChars) { + // Set the readIndex to the formatting indicator, so that the next loop will start writing from that paragraph symbol + readIndex = nextFormattingSequence + // Find the next § symbol after the formatting sequence + nextFormattingSequence = indexOf('§', startIndex = readIndex + 1) + } else { + // If this formatting sequence should be skipped (either a color code, or !keepFormatting or an incomplete formatting sequence without a code) + // Set the readIndex to after this formatting sequence, so that the next loop will skip over it before writing the string + readIndex = nextFormattingSequence + 2 + // Find the next § symbol after the formatting sequence + nextFormattingSequence = indexOf('§', startIndex = readIndex) + + // If the next read would be out of bound, reset the readIndex to the very end of the string, resulting in a "" string to be appended + readIndex = readIndex.coerceAtMost(this.length) } - builder.append(this[counter]) - counter++ } + // Finally, after the last formatting sequence was processed, copy over the last sequence of the string + cleanedString.append(this, readIndex, this.length) - return builder.toString() + // And turn the string builder into a string + return cleanedString.toString() } fun UUID.toDashlessUUID(): String { |