stdlib: StringBuilder: Use Apache Harmony reverse() implementation

This patch uses a Apache Harmony's approach to reverse surrogate
pairs.
This commit is contained in:
Ilya Matveev
2017-04-24 15:33:58 +07:00
committed by ilmat192
parent 7f9e65ef17
commit f958573d05
@@ -102,33 +102,69 @@ class StringBuilder private constructor (
}
}
// Based on Apache Harmony implementation.
fun reverse(): StringBuilder {
if (this.length < 2) {
return this
}
var end = length - 1
var front = 0
var end = array.lastIndex
var hasSurrogates = false
while (front < end) {
if (array[front].isSurrogate() || array[end].isSurrogate()) {
hasSurrogates = true
var frontHigh = array[0]
var endLow = array[end]
var allowFrontSur = true
var allowEndSur = true
while (front < length / 2) {
var frontLow = array[front + 1]
var endHigh = array[end - 1]
var surAtFront = allowFrontSur && frontLow.isLowSurrogate() && frontHigh.isHighSurrogate()
if (surAtFront && length < 3) {
return this
}
var surAtEnd = allowEndSur && endLow.isLowSurrogate() && endHigh.isHighSurrogate()
allowFrontSur = true
allowEndSur = true
when {
surAtFront && surAtEnd -> {
// Both surrogates - just exchange them.
array[end] = frontLow
array[end - 1] = frontHigh
array[front] = endHigh
array[front + 1] = endLow
frontHigh = array[front + 2]
endLow = array[end - 2]
front++
end--
}
!surAtFront && !surAtEnd -> {
// Neither surrogates - exchange only front/end.
array[end] = frontHigh
array[front] = endLow
frontHigh = frontLow
endLow = endHigh
}
surAtFront && !surAtEnd -> {
// Surrogate only at the front -
// move the low part, the high part will be moved as a usual character on the next iteration.
array[end] = frontLow
array[front] = endLow
endLow = endHigh
allowFrontSur = false
}
!surAtFront && surAtEnd -> {
// Surrogate only at the end -
// move the high part, the low part will be moved as a usual character on the next iteration.
array[end] = frontHigh
array[front] = endHigh
frontHigh = frontLow
allowEndSur = false
}
}
val tmp = array[front]
array[front] = array[end]
array[end] = tmp
front++
end--
}
// Reverse surrogate pairs back.
if (hasSurrogates) {
var i = 0
while (i < length - 1) {
if (array[i].isLowSurrogate() && array[i + 1].isHighSurrogate()) {
val tmp = array[i]
array[i] = array[i + 1]
array[i + 1] = tmp
i++
}
i++
}
if (length % 2 == 1 && (!allowEndSur || !allowFrontSur)) {
array[end] = if (allowFrontSur) endLow else frontHigh
}
return this
}