Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reshuffle code #7

Merged
merged 4 commits into from
Jan 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 28 additions & 18 deletions src/commonImplementation/kotlin/CodePoints.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,54 @@

package de.cketti.codepoints

import de.cketti.codepoints.internal.charCount as commonCharCount
import de.cketti.codepoints.internal.highSurrogate as commonHighSurrogate
import de.cketti.codepoints.internal.isBmpCodePoint as commonIsBmpCodePoint
import de.cketti.codepoints.internal.isSupplementaryCodePoint as commonIsSupplementaryCodePoint
import de.cketti.codepoints.internal.isSurrogatePair as commonIsSurrogatePair
import de.cketti.codepoints.internal.isValidCodePoint as commonIsValidCodePoint
import de.cketti.codepoints.internal.lowSurrogate as commonLowSurrogate
import de.cketti.codepoints.internal.toChars as commonToChars
import de.cketti.codepoints.internal.toCodePoint as commonToCodePoint

actual object CodePoints {
actual inline fun isValidCodePoint(codePoint: Int): Boolean {
return CommonCodePoints.isValidCodePoint(codePoint)
actual fun isValidCodePoint(codePoint: Int): Boolean {
return commonIsValidCodePoint(codePoint)
}

actual inline fun isBmpCodePoint(codePoint: Int): Boolean {
return CommonCodePoints.isBmpCodePoint(codePoint)
actual fun isBmpCodePoint(codePoint: Int): Boolean {
return commonIsBmpCodePoint(codePoint)
}

actual inline fun isSupplementaryCodePoint(codePoint: Int): Boolean {
return CommonCodePoints.isSupplementaryCodePoint(codePoint)
actual fun isSupplementaryCodePoint(codePoint: Int): Boolean {
return commonIsSupplementaryCodePoint(codePoint)
}

actual inline fun charCount(codePoint: Int): Int {
return CommonCodePoints.charCount(codePoint)
actual fun charCount(codePoint: Int): Int {
return commonCharCount(codePoint)
}

actual inline fun isSurrogatePair(highSurrogate: Char, lowSurrogate: Char): Boolean {
return CommonCodePoints.isSurrogatePair(highSurrogate, lowSurrogate)
actual fun isSurrogatePair(highSurrogate: Char, lowSurrogate: Char): Boolean {
return commonIsSurrogatePair(highSurrogate, lowSurrogate)
}

actual fun highSurrogate(codePoint: Int): Char {
return CommonCodePoints.highSurrogate(codePoint)
return commonHighSurrogate(codePoint)
}

actual fun lowSurrogate(codePoint: Int): Char {
return CommonCodePoints.lowSurrogate(codePoint)
return commonLowSurrogate(codePoint)
}

actual inline fun toCodePoint(highSurrogate: Char, lowSurrogate: Char): Int {
return CommonCodePoints.toCodePoint(highSurrogate, lowSurrogate)
actual fun toCodePoint(highSurrogate: Char, lowSurrogate: Char): Int {
return commonToCodePoint(highSurrogate, lowSurrogate)
}

actual inline fun toChars(codePoint: Int): CharArray {
return CommonCodePoints.toChars(codePoint)
actual fun toChars(codePoint: Int): CharArray {
return commonToChars(codePoint)
}

actual inline fun toChars(codePoint: Int, destination: CharArray, offset: Int): Int {
return CommonCodePoints.toChars(codePoint, destination, offset)
actual fun toChars(codePoint: Int, destination: CharArray, offset: Int): Int {
return commonToChars(codePoint, destination, offset)
}
}
77 changes: 0 additions & 77 deletions src/commonImplementation/kotlin/CommonCodePoints.kt

This file was deleted.

12 changes: 0 additions & 12 deletions src/commonImplementation/kotlin/CommonStringBuilderFunctions.kt

This file was deleted.

92 changes: 0 additions & 92 deletions src/commonImplementation/kotlin/CommonStringFunctions.kt

This file was deleted.

3 changes: 2 additions & 1 deletion src/commonImplementation/kotlin/StringBuilderExtensions.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package de.cketti.codepoints

import kotlin.text.StringBuilder
import de.cketti.codepoints.internal.appendCodePoint as commonAppendCodePoint

actual fun StringBuilder.appendCodePoint(codePoint: Int): StringBuilder = apply {
CommonStringBuilderFunctions.appendCodePoint(this, codePoint)
commonAppendCodePoint(this, codePoint)
}
21 changes: 13 additions & 8 deletions src/commonImplementation/kotlin/StringExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,23 @@

package de.cketti.codepoints

actual inline fun String.codePointAt(index: Int): Int {
return CommonStringFunctions.codePointAt(this, index)
import de.cketti.codepoints.internal.codePointAt as commonCodePointAt
import de.cketti.codepoints.internal.codePointBefore as commonCodePointBefore
import de.cketti.codepoints.internal.codePointCount as commonCodePointCount
import de.cketti.codepoints.internal.offsetByCodePoints as commonOffsetByCodePoints

actual fun String.codePointAt(index: Int): Int {
return commonCodePointAt(this, index)
}

actual inline fun String.codePointBefore(index: Int): Int {
return CommonStringFunctions.codePointBefore(this, index)
actual fun String.codePointBefore(index: Int): Int {
return commonCodePointBefore(this, index)
}

actual inline fun String.codePointCount(beginIndex: Int, endIndex: Int): Int {
return CommonStringFunctions.codePointCount(this, beginIndex, endIndex)
actual fun String.codePointCount(beginIndex: Int, endIndex: Int): Int {
return commonCodePointCount(this, beginIndex, endIndex)
}

actual inline fun String.offsetByCodePoints(index: Int, codePointOffset: Int): Int {
return CommonStringFunctions.offsetByCodePoints(this, index, codePointOffset)
actual fun String.offsetByCodePoints(index: Int, codePointOffset: Int): Int {
return commonOffsetByCodePoints(this, index, codePointOffset)
}
75 changes: 75 additions & 0 deletions src/commonImplementation/kotlin/internal/CommonCodePoints.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package de.cketti.codepoints.internal

private const val MIN_SUPPLEMENTARY_CODE_POINT = 0x10000
private const val MAX_CODE_POINT = 0x10FFFF

private const val MIN_HIGH_SURROGATE = 0xD800
private const val MIN_LOW_SURROGATE = 0xDC00

private const val SURROGATE_DECODE_OFFSET =
MIN_SUPPLEMENTARY_CODE_POINT - (MIN_HIGH_SURROGATE shl 10) - MIN_LOW_SURROGATE

private const val HIGH_SURROGATE_ENCODE_OFFSET =
(MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT ushr 10))

internal fun isValidCodePoint(codePoint: Int): Boolean {
return codePoint in 0..MAX_CODE_POINT
}

internal fun isBmpCodePoint(codePoint: Int): Boolean {
return codePoint ushr 16 == 0
}

internal fun isSupplementaryCodePoint(codePoint: Int): Boolean {
return codePoint in MIN_SUPPLEMENTARY_CODE_POINT..MAX_CODE_POINT
}

internal fun charCount(codePoint: Int): Int {
return if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) 1 else 2
}

internal fun isSurrogatePair(highSurrogate: Char, lowSurrogate: Char): Boolean {
return highSurrogate.isHighSurrogate() && lowSurrogate.isLowSurrogate()
}

internal fun highSurrogate(codePoint: Int): Char {
return ((codePoint ushr 10) + HIGH_SURROGATE_ENCODE_OFFSET).toChar()
}

internal fun lowSurrogate(codePoint: Int): Char {
return ((codePoint and 0x3FF) + MIN_LOW_SURROGATE).toChar()
}

internal fun toCodePoint(highSurrogate: Char, lowSurrogate: Char): Int {
return (highSurrogate.code shl 10) + lowSurrogate.code + SURROGATE_DECODE_OFFSET
}

internal fun toChars(codePoint: Int): CharArray {
return if (isBmpCodePoint(codePoint)) {
charArrayOf(codePoint.toChar())
} else {
charArrayOf(highSurrogate(codePoint), lowSurrogate(codePoint))
}
}

internal fun toChars(codePoint: Int, destination: CharArray, offset: Int): Int {
if (isBmpCodePoint(codePoint)) {
destination.setSafe(offset, codePoint.toChar())
return 1
} else {
// When writing the low surrogate succeeds but writing the high surrogate fails (offset = -1), the
// destination will be modified even though the method throws. This feels wrong, but matches the behavior
// of the Java stdlib implementation.
destination.setSafe(offset + 1, lowSurrogate(codePoint))
destination.setSafe(offset, highSurrogate(codePoint))
return 2
}
}

private fun CharArray.setSafe(index: Int, value: Char) {
if (index !in this.indices) {
throw IndexOutOfBoundsException("Size: $size, offset: $index")
}

this[index] = value
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package de.cketti.codepoints.internal

internal fun appendCodePoint(builder: StringBuilder, codePoint: Int) {
if (isBmpCodePoint(codePoint)) {
builder.append(codePoint.toChar())
} else {
builder.append(highSurrogate(codePoint))
builder.append(lowSurrogate(codePoint))
}
}
Loading