[K/N] Experimental Char code point constants and functions

Internalize WASM Char code point functions.

As a part of efforts to stabilize Native stdlib.
This commit is contained in:
Abduqodiri Qurbonzoda
2023-04-19 15:19:11 +03:00
committed by Space Team
parent c6eaadb44f
commit b25f3be81b
18 changed files with 153 additions and 49 deletions
@@ -77,6 +77,7 @@ internal fun Int.isCaseIgnorable(): Boolean {
return index >= 0 && this <= caseIgnorableEnd[index]
}
@OptIn(kotlin.experimental.ExperimentalNativeApi::class)
private fun String.codePointBefore(index: Int): Int {
val low = this[index]
if (low.isLowSurrogate() && index - 1 >= 0) {
@@ -10,6 +10,7 @@ package kotlin.text
// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib
//
@OptIn(kotlin.experimental.ExperimentalNativeApi::class)
internal fun String.codePointAt(index: Int): Int {
val high = this[index]
if (high.isHighSurrogate() && index + 1 < this.length) {
@@ -21,10 +22,10 @@ internal fun String.codePointAt(index: Int): Int {
return high.code
}
internal fun Int.charCount(): Int = if (this >= Char.MIN_SUPPLEMENTARY_CODE_POINT) 2 else 1
internal fun Int.charCount(): Int = if (this > Char.MAX_VALUE.code) 2 else 1
internal fun StringBuilder.appendCodePoint(codePoint: Int) {
if (codePoint < Char.MIN_SUPPLEMENTARY_CODE_POINT) {
if (codePoint <= Char.MAX_VALUE.code) {
append(codePoint.toChar())
} else {
append(Char.MIN_HIGH_SURROGATE + ((codePoint - 0x10000) shr 10))
@@ -6,6 +6,7 @@
package kotlin
import kotlin.experimental.ExperimentalNativeApi
import kotlin.native.internal.GCUnsafeCall
import kotlin.native.internal.TypedIntrinsic
import kotlin.native.internal.IntrinsicType
@@ -151,18 +152,30 @@ public class Char private constructor() : Comparable<Char> {
public const val MAX_SURROGATE: Char = MAX_LOW_SURROGATE
/**
* The minimum value of a supplementary code point, `\u0x10000`. Kotlin/Native specific.
* The minimum value of a supplementary code point, `\u0x10000`.
*
* Note that this constant is experimental.
* In the future it could be deprecated in favour of another constant of a `CodePoint` type.
*/
@ExperimentalNativeApi
public const val MIN_SUPPLEMENTARY_CODE_POINT: Int = 0x10000
/**
* The minimum value of a Unicode code point. Kotlin/Native specific.
* The minimum value of a Unicode code point.
*
* Note that this constant is experimental.
* In the future it could be deprecated in favour of another constant of a `CodePoint` type.
*/
@ExperimentalNativeApi
public const val MIN_CODE_POINT = 0x000000
/**
* The maximum value of a Unicode code point. Kotlin/Native specific.
* The maximum value of a Unicode code point.
*
* Note that this constant is experimental.
* In the future it could be deprecated in favour of another constant of a `CodePoint` type.
*/
@ExperimentalNativeApi
public const val MAX_CODE_POINT = 0X10FFFF
/**
@@ -5,6 +5,7 @@
package kotlin.text
import kotlin.experimental.ExperimentalNativeApi
import kotlin.native.internal.GCUnsafeCall
/**
@@ -30,6 +31,58 @@ external public actual fun Char.isLowSurrogate(): Boolean
@GCUnsafeCall("Kotlin_Char_isISOControl")
external public actual fun Char.isISOControl(): Boolean
/**
* Converts a surrogate pair to a unicode code point. Doesn't validate that the characters are a valid surrogate pair.
*
* Note that this function is unstable.
* In the future it could be deprecated in favour of an overload that would return a `CodePoint` type.
*/
@ExperimentalNativeApi
// TODO: Consider removing from public API
public fun Char.Companion.toCodePoint(high: Char, low: Char): Int =
(((high - MIN_HIGH_SURROGATE) shl 10) or (low - MIN_LOW_SURROGATE)) + 0x10000
/**
* Checks if the codepoint specified is a supplementary codepoint or not.
*
* Note that this function is unstable.
* In the future it could be deprecated in favour of an overload that would accept a `CodePoint` type.
*/
@ExperimentalNativeApi
// TODO: Consider removing from public API
public fun Char.Companion.isSupplementaryCodePoint(codepoint: Int): Boolean =
codepoint in MIN_SUPPLEMENTARY_CODE_POINT..MAX_CODE_POINT
/**
* Checks if the specified [high] and [low] chars are [Char.isHighSurrogate] and [Char.isLowSurrogate] correspondingly.
*/
@ExperimentalNativeApi
// TODO: Consider removing from public API
public fun Char.Companion.isSurrogatePair(high: Char, low: Char): Boolean = high.isHighSurrogate() && low.isLowSurrogate()
/**
* Converts the codepoint specified to a char array. If the codepoint is not supplementary, the method will
* return an array with one element otherwise it will return an array A with a high surrogate in A[0] and
* a low surrogate in A[1].
*
*
* Note that this function is unstable.
* In the future it could be deprecated in favour of an overload that would accept a `CodePoint` type.
*/
@ExperimentalNativeApi
// TODO: Consider removing from public API
@Suppress("DEPRECATION")
public fun Char.Companion.toChars(codePoint: Int): CharArray =
when {
codePoint in 0 until MIN_SUPPLEMENTARY_CODE_POINT -> charArrayOf(codePoint.toChar())
codePoint in MIN_SUPPLEMENTARY_CODE_POINT..MAX_CODE_POINT -> {
val low = ((codePoint - 0x10000) and 0x3FF) + MIN_LOW_SURROGATE.toInt()
val high = (((codePoint - 0x10000) ushr 10) and 0x3FF) + MIN_HIGH_SURROGATE.toInt()
charArrayOf(high.toChar(), low.toChar())
}
else -> throw IllegalArgumentException()
}
@SharedImmutable
private val digits = intArrayOf(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,