Unverified Commit 2a47e23a authored by Shagen Ogandzhanian's avatar Shagen Ogandzhanian Committed by GitHub

Use convertToZeroTerminatedString on both wasm and js targets (#972)

This is supposed to be fix for
https://github.com/JetBrains/skiko/issues/967

The idea is pass strings as (utf8) byte arrays directly through the
border just like we do it on native
parent c1f81974
...@@ -33,6 +33,9 @@ class ManagedStringTest { ...@@ -33,6 +33,9 @@ class ManagedStringTest {
val ms3 = ManagedString("你好!") val ms3 = ManagedString("你好!")
assertEquals("你好!", ms3.toString()) assertEquals("你好!", ms3.toString())
val msEmpty = ManagedString("")
assertEquals("", msEmpty.toString())
} }
@Test @Test
...@@ -45,6 +48,9 @@ class ManagedStringTest { ...@@ -45,6 +48,9 @@ class ManagedStringTest {
val ms3 = ManagedString("你好").append(",世界") val ms3 = ManagedString("你好").append(",世界")
assertEquals("你好,世界", ms3.toString()) assertEquals("你好,世界", ms3.toString())
val msEmpty = ManagedString("Empty string").append("")
assertEquals("Empty string", msEmpty.toString())
} }
@Test @Test
...@@ -57,6 +63,9 @@ class ManagedStringTest { ...@@ -57,6 +63,9 @@ class ManagedStringTest {
val ms3 = ManagedString("世界").insert(0,"你好,") val ms3 = ManagedString("世界").insert(0,"你好,")
assertEquals("你好,世界", ms3.toString()) assertEquals("你好,世界", ms3.toString())
val msEmpty = ManagedString("Empty string").insert(1, "").insert(0, "")
assertEquals("Empty string", msEmpty.toString())
} }
@Test @Test
...@@ -72,5 +81,8 @@ class ManagedStringTest { ...@@ -72,5 +81,8 @@ class ManagedStringTest {
val ms4 = ManagedString("你好,世界!").remove(from = 2, length = 3) // ',' is 1 symbol val ms4 = ManagedString("你好,世界!").remove(from = 2, length = 3) // ',' is 1 symbol
assertEquals("你好!", ms4.toString()) assertEquals("你好!", ms4.toString())
val msEmpty = ManagedString("World!").remove(from = 2, length = 0)
assertEquals("World!", msEmpty.toString())
} }
} }
...@@ -63,18 +63,13 @@ internal actual fun fromWasm(src: NativePointer, result: DoubleArray) { ...@@ -63,18 +63,13 @@ internal actual fun fromWasm(src: NativePointer, result: DoubleArray) {
result.asDynamic().set(HEAPF64.subarray(startIndex, startIndex + result.size)) result.asDynamic().set(HEAPF64.subarray(startIndex, startIndex + result.size))
} }
internal actual external fun stringToUTF8(str: String, outPtr: NativePointer, maxBytesToWrite: Int)
internal actual class InteropScope actual constructor() { internal actual class InteropScope actual constructor() {
private val elements = mutableListOf<NativePointer>() private val elements = mutableListOf<NativePointer>()
private var callbacksInitialized = false private var callbacksInitialized = false
actual fun toInterop(string: String?): InteropPointer { actual fun toInterop(string: String?): InteropPointer {
return if (string != null) { return if (string != null) {
val data = _malloc(string.length * 4) toInterop(convertToZeroTerminatedString(string))
stringToUTF8(string, data, string.length * 4)
elements.add(data)
data
} else { } else {
0 0
} }
......
...@@ -64,12 +64,6 @@ internal external fun _malloc(size: Int): NativePointer ...@@ -64,12 +64,6 @@ internal external fun _malloc(size: Int): NativePointer
@ModuleImport("./skiko.mjs", "free") @ModuleImport("./skiko.mjs", "free")
internal external fun _free(ptr: NativePointer) internal external fun _free(ptr: NativePointer)
private external fun lengthBytesUTF8(str: String): Int
internal expect fun stringToUTF8(str: String, outPtr: NativePointer, maxBytesToWrite: Int)
private external fun UTF8ToString(ptr: NativePointer): String
// Data copying routines. // Data copying routines.
internal expect fun toWasm(dest: NativePointer, src: ByteArray) internal expect fun toWasm(dest: NativePointer, src: ByteArray)
internal expect fun toWasm(dest: NativePointer, src: ShortArray) internal expect fun toWasm(dest: NativePointer, src: ShortArray)
......
package org.jetbrains.skia.impl
/**
* Converts String to zero-terminated utf-8 byte array.
*/
internal fun convertToZeroTerminatedString(string: String): ByteArray {
// C++ needs char* with zero byte at the end. So we need to copy array with an extra zero byte.
val utf8 = string.encodeToByteArray() // encodeToByteArray encodes to utf8
// TODO Remove array copy, use `skString(data, length)` instead of `skString(data)`
return utf8.copyOf(utf8.size + 1)
}
\ No newline at end of file
...@@ -281,14 +281,3 @@ private external fun initCallbacks( ...@@ -281,14 +281,3 @@ private external fun initCallbacks(
callVoid: COpaquePointer, callVoid: COpaquePointer,
dispose: COpaquePointer dispose: COpaquePointer
) )
/**
* Converts String to zero-terminated utf-8 byte array.
*/
private fun convertToZeroTerminatedString(string: String): ByteArray {
// C++ needs char* with zero byte at the end. So we need to copy array with an extra zero byte.
val utf8 = string.encodeToByteArray() // encodeToByteArray encodes to utf8
// TODO Remove array copy, use `skString(data, length)` instead of `skString(data)`
return utf8.copyOf(utf8.size + 1)
}
...@@ -124,30 +124,13 @@ internal actual fun fromWasm(src: NativePointer, result: DoubleArray) { ...@@ -124,30 +124,13 @@ internal actual fun fromWasm(src: NativePointer, result: DoubleArray) {
} }
} }
internal actual fun stringToUTF8(str: String, outPtr: NativePointer, maxBytesToWrite: Int) {
if (maxBytesToWrite <= 0) return
val utf8 = str.encodeToByteArray()
val lastIndex = minOf(maxBytesToWrite - 1, utf8.size)
var index = 0
while (index < lastIndex) {
skia_memSetByte(outPtr + index, utf8[index])
index++
}
skia_memSetByte(outPtr + index, 0)
}
internal actual class InteropScope actual constructor() { internal actual class InteropScope actual constructor() {
private val elements = mutableListOf<NativePointer>() private val elements = mutableListOf<NativePointer>()
private var callbacksInitialized = false private var callbacksInitialized = false
actual fun toInterop(string: String?): InteropPointer { actual fun toInterop(string: String?): InteropPointer {
return if (string != null) { return if (string != null) {
val data = _malloc(string.length * 4) toInterop(convertToZeroTerminatedString(string))
stringToUTF8(string, data, string.length * 4)
elements.add(data)
data
} else { } else {
0 0
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment