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 { fun reverse(): StringBuilder {
var front = 0 if (this.length < 2) {
var end = array.lastIndex return this
var hasSurrogates = false
while (front < end) {
if (array[front].isSurrogate() || array[end].isSurrogate()) {
hasSurrogates = true
} }
val tmp = array[front] var end = length - 1
array[front] = array[end] var front = 0
array[end] = tmp 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++ front++
end-- end--
} }
!surAtFront && !surAtEnd -> {
// Reverse surrogate pairs back. // Neither surrogates - exchange only front/end.
if (hasSurrogates) { array[end] = frontHigh
var i = 0 array[front] = endLow
while (i < length - 1) { frontHigh = frontLow
if (array[i].isLowSurrogate() && array[i + 1].isHighSurrogate()) { endLow = endHigh
val tmp = array[i]
array[i] = array[i + 1]
array[i + 1] = tmp
i++
} }
i++ 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
}
}
front++
end--
}
if (length % 2 == 1 && (!allowEndSur || !allowFrontSur)) {
array[end] = if (allowFrontSur) endLow else frontHigh
} }
return this return this
} }