Optimize CPointer.toKStringFromUtf8 on Native
Use strlen and stop allocating intermediate ByteArray to make the performance comparable to ByteArray.decodeToString(). Partially fix KT-44357.
This commit is contained in:
committed by
Vasily Levchenko
parent
dc2d014504
commit
f766a3eae4
@@ -21,9 +21,22 @@ import java.io.File
|
|||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
|
|
||||||
internal fun decodeFromUtf8(bytes: ByteArray) = String(bytes)
|
private fun decodeFromUtf8(bytes: ByteArray) = String(bytes)
|
||||||
internal fun encodeToUtf8(str: String) = str.toByteArray()
|
internal fun encodeToUtf8(str: String) = str.toByteArray()
|
||||||
|
|
||||||
|
internal fun CPointer<ByteVar>.toKStringFromUtf8Impl(): String {
|
||||||
|
val nativeBytes = this
|
||||||
|
|
||||||
|
var length = 0
|
||||||
|
while (nativeBytes[length] != 0.toByte()) {
|
||||||
|
++length
|
||||||
|
}
|
||||||
|
|
||||||
|
val bytes = ByteArray(length)
|
||||||
|
nativeMemUtils.getByteArray(nativeBytes.pointed, bytes, length)
|
||||||
|
return decodeFromUtf8(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
fun bitsToFloat(bits: Int): Float = java.lang.Float.intBitsToFloat(bits)
|
fun bitsToFloat(bits: Int): Float = java.lang.Float.intBitsToFloat(bits)
|
||||||
fun bitsToDouble(bits: Long): Double = java.lang.Double.longBitsToDouble(bits)
|
fun bitsToDouble(bits: Long): Double = java.lang.Double.longBitsToDouble(bits)
|
||||||
|
|
||||||
|
|||||||
@@ -507,18 +507,7 @@ public val String.utf32: CValues<IntVar>
|
|||||||
/**
|
/**
|
||||||
* @return the [kotlin.String] decoded from given zero-terminated UTF-8-encoded C string.
|
* @return the [kotlin.String] decoded from given zero-terminated UTF-8-encoded C string.
|
||||||
*/
|
*/
|
||||||
public fun CPointer<ByteVar>.toKStringFromUtf8(): String {
|
public fun CPointer<ByteVar>.toKStringFromUtf8(): String = this.toKStringFromUtf8Impl()
|
||||||
val nativeBytes = this
|
|
||||||
|
|
||||||
var length = 0
|
|
||||||
while (nativeBytes[length] != 0.toByte()) {
|
|
||||||
++length
|
|
||||||
}
|
|
||||||
|
|
||||||
val bytes = ByteArray(length)
|
|
||||||
nativeMemUtils.getByteArray(nativeBytes.pointed, bytes, length)
|
|
||||||
return decodeFromUtf8(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the [kotlin.String] decoded from given zero-terminated UTF-8-encoded C string.
|
* @return the [kotlin.String] decoded from given zero-terminated UTF-8-encoded C string.
|
||||||
|
|||||||
@@ -20,9 +20,11 @@ import kotlin.native.internal.Intrinsic
|
|||||||
import kotlin.native.internal.TypedIntrinsic
|
import kotlin.native.internal.TypedIntrinsic
|
||||||
import kotlin.native.internal.IntrinsicType
|
import kotlin.native.internal.IntrinsicType
|
||||||
|
|
||||||
internal fun decodeFromUtf8(bytes: ByteArray): String = bytes.decodeToString()
|
|
||||||
internal fun encodeToUtf8(str: String): ByteArray = str.encodeToByteArray()
|
internal fun encodeToUtf8(str: String): ByteArray = str.encodeToByteArray()
|
||||||
|
|
||||||
|
@SymbolName("Kotlin_CString_toKStringFromUtf8Impl")
|
||||||
|
internal external fun CPointer<ByteVar>.toKStringFromUtf8Impl(): String
|
||||||
|
|
||||||
@TypedIntrinsic(IntrinsicType.INTEROP_BITS_TO_FLOAT)
|
@TypedIntrinsic(IntrinsicType.INTEROP_BITS_TO_FLOAT)
|
||||||
external fun bitsToFloat(bits: Int): Float
|
external fun bitsToFloat(bits: Int): Float
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,10 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "Alloc.h"
|
#include "Alloc.h"
|
||||||
|
#include "KString.h"
|
||||||
#include "Memory.h"
|
#include "Memory.h"
|
||||||
#include "MemorySharedRefs.hpp"
|
#include "MemorySharedRefs.hpp"
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
@@ -42,4 +44,8 @@ OBJ_GETTER(Kotlin_Interop_derefStablePointer, KNativePtr pointer) {
|
|||||||
RETURN_OBJ(holder->ref<ErrorPolicy::kThrow>());
|
RETURN_OBJ(holder->ref<ErrorPolicy::kThrow>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OBJ_GETTER(Kotlin_CString_toKStringFromUtf8Impl, const char* cstring) {
|
||||||
|
RETURN_RESULT_OF(StringFromUtf8Buffer, cstring, strlen(cstring));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -511,6 +511,13 @@ OBJ_GETTER(Kotlin_ByteArray_unsafeStringFromUtf8, KConstRef thiz, KInt start, KI
|
|||||||
RETURN_RESULT_OF(utf8ToUtf16, rawString, size);
|
RETURN_RESULT_OF(utf8ToUtf16, rawString, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OBJ_GETTER(StringFromUtf8Buffer, const char* start, size_t size) {
|
||||||
|
if (size == 0) {
|
||||||
|
RETURN_RESULT_OF0(TheEmptyString);
|
||||||
|
}
|
||||||
|
RETURN_RESULT_OF(utf8ToUtf16, start, size);
|
||||||
|
}
|
||||||
|
|
||||||
OBJ_GETTER(Kotlin_String_unsafeStringToUtf8, KString thiz, KInt start, KInt size) {
|
OBJ_GETTER(Kotlin_String_unsafeStringToUtf8, KString thiz, KInt start, KInt size) {
|
||||||
RETURN_RESULT_OF(unsafeUtf16ToUtf8Impl<utf8::with_replacement::utf16to8>, thiz, start, size);
|
RETURN_RESULT_OF(unsafeUtf16ToUtf8Impl<utf8::with_replacement::utf16to8>, thiz, start, size);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ OBJ_GETTER(CreateStringFromUtf8, const char* utf8, uint32_t lengthBytes);
|
|||||||
char* CreateCStringFromString(KConstRef kstring);
|
char* CreateCStringFromString(KConstRef kstring);
|
||||||
void DisposeCString(char* cstring);
|
void DisposeCString(char* cstring);
|
||||||
|
|
||||||
|
OBJ_GETTER(StringFromUtf8Buffer, const char* start, size_t size);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user