ShellComparator.kt
package de.pflugradts.passbird.domain.model.shell
import java.util.concurrent.atomic.AtomicInteger
private val sortReference = buildSortReference()
private fun buildSortReference(): Map<Int, Int> {
val sortReferenceMap = mutableMapOf<Int, Int>()
val index = AtomicInteger(0)
val assignSlot: (Int) -> Unit = { sortReferenceMap[it] = index.getAndIncrement() }
(MIN_ASCII_VALUE..MAX_ASCII_VALUE).filter { PlainValue.plainValueOf(it).isSymbol }.forEach(assignSlot)
(FIRST_DIGIT_INDEX..LAST_DIGIT_INDEX).forEach(assignSlot)
val lowercaseRange = (FIRST_LOWERCASE_INDEX..LAST_LOWERCASE_INDEX)
val uppercaseRange = (FIRST_UPPERCASE_INDEX..LAST_UPPERCASE_INDEX)
lowercaseRange.forEachIndexed { i, _ ->
sortReferenceMap[uppercaseRange.elementAt(i)] = index.get()
sortReferenceMap[lowercaseRange.elementAt(i)] = index.getAndIncrement()
}
return sortReferenceMap.toMap()
}
class ShellComparator : Comparator<Shell> {
override fun compare(shell1: Shell, shell2: Shell): Int {
if (shell1 == shell2) return 0
val reverse = shell1.size > shell2.size
val b1 = if (reverse) shell2.toByteArray() else shell1.toByteArray()
val b2 = if (reverse) shell1.toByteArray() else shell2.toByteArray()
var index = -1
var result = if (b1.size == b2.size) 0 else -1
while (++index < b1.size) {
val b1SortIndex = sortReference[b1[index].toInt()]
val b2SortIndex = sortReference[b2[index].toInt()]
if (b1SortIndex!!.compareTo(b2SortIndex!!) != 0) {
result = if (b1SortIndex < b2SortIndex) -1 else 1
break
}
}
return if (reverse) result * -1 else result
}
}