Skip to content

Commit 31938c1

Browse files
authored
Merge pull request #17 from JakeWharton/jw.inline.2023-01-25
Inline implementations in actuals
2 parents df119f7 + bb929ac commit 31938c1

File tree

6 files changed

+129
-207
lines changed

6 files changed

+129
-207
lines changed
Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,77 @@
1-
@file:Suppress("NOTHING_TO_INLINE")
2-
31
package de.cketti.codepoints
42

5-
import de.cketti.codepoints.internal.charCount as commonCharCount
6-
import de.cketti.codepoints.internal.highSurrogate as commonHighSurrogate
7-
import de.cketti.codepoints.internal.isBmpCodePoint as commonIsBmpCodePoint
8-
import de.cketti.codepoints.internal.isSupplementaryCodePoint as commonIsSupplementaryCodePoint
9-
import de.cketti.codepoints.internal.isSurrogatePair as commonIsSurrogatePair
10-
import de.cketti.codepoints.internal.isValidCodePoint as commonIsValidCodePoint
11-
import de.cketti.codepoints.internal.lowSurrogate as commonLowSurrogate
12-
import de.cketti.codepoints.internal.toChars as commonToChars
13-
import de.cketti.codepoints.internal.toCodePoint as commonToCodePoint
14-
153
actual object CodePoints {
4+
private const val MIN_SUPPLEMENTARY_CODE_POINT = 0x10000
5+
private const val MAX_CODE_POINT = 0x10FFFF
6+
7+
private const val MIN_HIGH_SURROGATE = 0xD800
8+
private const val MIN_LOW_SURROGATE = 0xDC00
9+
10+
private const val SURROGATE_DECODE_OFFSET =
11+
MIN_SUPPLEMENTARY_CODE_POINT - (MIN_HIGH_SURROGATE shl 10) - MIN_LOW_SURROGATE
12+
13+
private const val HIGH_SURROGATE_ENCODE_OFFSET =
14+
(MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT ushr 10))
15+
1616
actual fun isValidCodePoint(codePoint: Int): Boolean {
17-
return commonIsValidCodePoint(codePoint)
17+
return codePoint in 0..MAX_CODE_POINT
1818
}
1919

2020
actual fun isBmpCodePoint(codePoint: Int): Boolean {
21-
return commonIsBmpCodePoint(codePoint)
21+
return codePoint ushr 16 == 0
2222
}
2323

2424
actual fun isSupplementaryCodePoint(codePoint: Int): Boolean {
25-
return commonIsSupplementaryCodePoint(codePoint)
25+
return codePoint in MIN_SUPPLEMENTARY_CODE_POINT..MAX_CODE_POINT
2626
}
2727

2828
actual fun charCount(codePoint: Int): Int {
29-
return commonCharCount(codePoint)
29+
return if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) 1 else 2
3030
}
3131

3232
actual fun isSurrogatePair(highSurrogate: Char, lowSurrogate: Char): Boolean {
33-
return commonIsSurrogatePair(highSurrogate, lowSurrogate)
33+
return highSurrogate.isHighSurrogate() && lowSurrogate.isLowSurrogate()
3434
}
3535

3636
actual fun highSurrogate(codePoint: Int): Char {
37-
return commonHighSurrogate(codePoint)
37+
return ((codePoint ushr 10) + HIGH_SURROGATE_ENCODE_OFFSET).toChar()
3838
}
3939

4040
actual fun lowSurrogate(codePoint: Int): Char {
41-
return commonLowSurrogate(codePoint)
41+
return ((codePoint and 0x3FF) + MIN_LOW_SURROGATE).toChar()
4242
}
4343

4444
actual fun toCodePoint(highSurrogate: Char, lowSurrogate: Char): Int {
45-
return commonToCodePoint(highSurrogate, lowSurrogate)
45+
return (highSurrogate.code shl 10) + lowSurrogate.code + SURROGATE_DECODE_OFFSET
4646
}
4747

4848
actual fun toChars(codePoint: Int): CharArray {
49-
return commonToChars(codePoint)
49+
return if (isBmpCodePoint(codePoint)) {
50+
charArrayOf(codePoint.toChar())
51+
} else {
52+
charArrayOf(highSurrogate(codePoint), lowSurrogate(codePoint))
53+
}
5054
}
5155

5256
actual fun toChars(codePoint: Int, destination: CharArray, offset: Int): Int {
53-
return commonToChars(codePoint, destination, offset)
57+
if (isBmpCodePoint(codePoint)) {
58+
destination.setSafe(offset, codePoint.toChar())
59+
return 1
60+
} else {
61+
// When writing the low surrogate succeeds but writing the high surrogate fails (offset = -1), the
62+
// destination will be modified even though the method throws. This feels wrong, but matches the behavior
63+
// of the Java stdlib implementation.
64+
destination.setSafe(offset + 1, lowSurrogate(codePoint))
65+
destination.setSafe(offset, highSurrogate(codePoint))
66+
return 2
67+
}
68+
}
69+
70+
private fun CharArray.setSafe(index: Int, value: Char) {
71+
if (index !in this.indices) {
72+
throw IndexOutOfBoundsException("Size: $size, offset: $index")
73+
}
74+
75+
this[index] = value
5476
}
5577
}
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
package de.cketti.codepoints
22

3+
import de.cketti.codepoints.CodePoints.highSurrogate
4+
import de.cketti.codepoints.CodePoints.isBmpCodePoint
5+
import de.cketti.codepoints.CodePoints.lowSurrogate
36
import kotlin.text.StringBuilder
4-
import de.cketti.codepoints.internal.appendCodePoint as commonAppendCodePoint
57

68
actual fun StringBuilder.appendCodePoint(codePoint: Int): StringBuilder = apply {
7-
commonAppendCodePoint(this, codePoint)
9+
if (isBmpCodePoint(codePoint)) {
10+
append(codePoint.toChar())
11+
} else {
12+
append(highSurrogate(codePoint))
13+
append(lowSurrogate(codePoint))
14+
}
815
}
Lines changed: 76 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,90 @@
1-
@file:Suppress("NOTHING_TO_INLINE")
2-
31
package de.cketti.codepoints
42

5-
import de.cketti.codepoints.internal.codePointAt as commonCodePointAt
6-
import de.cketti.codepoints.internal.codePointBefore as commonCodePointBefore
7-
import de.cketti.codepoints.internal.codePointCount as commonCodePointCount
8-
import de.cketti.codepoints.internal.offsetByCodePoints as commonOffsetByCodePoints
3+
import de.cketti.codepoints.CodePoints.toCodePoint
94

105
actual fun String.codePointAt(index: Int): Int {
11-
return commonCodePointAt(this, index)
6+
if (index !in indices) throw IndexOutOfBoundsException()
7+
8+
val firstChar = this[index]
9+
if (firstChar.isHighSurrogate() && index + 1 < length) {
10+
val nextChar = this[index + 1]
11+
if (nextChar.isLowSurrogate()) {
12+
return toCodePoint(firstChar, nextChar)
13+
}
14+
}
15+
16+
return firstChar.code
1217
}
1318

1419
actual fun String.codePointBefore(index: Int): Int {
15-
return commonCodePointBefore(this, index)
20+
val startIndex = index - 1
21+
if (startIndex !in indices) throw IndexOutOfBoundsException()
22+
23+
val firstChar = this[startIndex]
24+
if (firstChar.isLowSurrogate() && startIndex - 1 >= 0) {
25+
val previousChar = this[startIndex - 1]
26+
if (previousChar.isHighSurrogate()) {
27+
return toCodePoint(previousChar, firstChar)
28+
}
29+
}
30+
31+
return firstChar.code
1632
}
1733

1834
actual fun String.codePointCount(beginIndex: Int, endIndex: Int): Int {
19-
return commonCodePointCount(this, beginIndex, endIndex)
35+
if (beginIndex < 0 || endIndex > length || beginIndex > endIndex) throw IndexOutOfBoundsException()
36+
37+
var index = beginIndex
38+
var count = 0
39+
do {
40+
val firstChar = this[index]
41+
index++
42+
if (firstChar.isHighSurrogate() && index < endIndex) {
43+
val nextChar = this[index]
44+
if (nextChar.isLowSurrogate()) {
45+
index++
46+
}
47+
}
48+
49+
count++
50+
} while (index < endIndex)
51+
52+
return count
2053
}
2154

2255
actual fun String.offsetByCodePoints(index: Int, codePointOffset: Int): Int {
23-
return commonOffsetByCodePoints(this, index, codePointOffset)
56+
if (index !in 0..length) throw IndexOutOfBoundsException()
57+
if (codePointOffset == 0) return index
58+
59+
if (codePointOffset > 0) {
60+
var currentIndex = index
61+
repeat(codePointOffset) {
62+
if (currentIndex > lastIndex) throw IndexOutOfBoundsException()
63+
val firstChar = this[currentIndex]
64+
currentIndex++
65+
if (firstChar.isHighSurrogate() && currentIndex <= lastIndex) {
66+
val nextChar = this[currentIndex]
67+
if (nextChar.isLowSurrogate()) {
68+
currentIndex++
69+
}
70+
}
71+
}
72+
73+
return currentIndex
74+
} else {
75+
var currentIndex = index - 1
76+
repeat(-codePointOffset) {
77+
if (currentIndex < 0) throw IndexOutOfBoundsException()
78+
val firstChar = this[currentIndex]
79+
currentIndex--
80+
if (firstChar.isLowSurrogate() && currentIndex >= 0) {
81+
val previousChar = this[currentIndex]
82+
if (previousChar.isHighSurrogate()) {
83+
currentIndex--
84+
}
85+
}
86+
}
87+
88+
return currentIndex + 1
89+
}
2490
}

src/commonImplementation/kotlin/internal/CommonCodePoints.kt

Lines changed: 0 additions & 75 deletions
This file was deleted.

src/commonImplementation/kotlin/internal/CommonStringBuilderFunctions.kt

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/commonImplementation/kotlin/internal/CommonStringFunctions.kt

Lines changed: 0 additions & 88 deletions
This file was deleted.

0 commit comments

Comments
 (0)