Support unsigned types (#1854)

(cherry picked from commit 7b46f93033146462619376d8d008343c2ee75e00)
This commit is contained in:
SvyatoslavScherbina
2018-08-17 17:48:11 +03:00
committed by Vasily Levchenko
parent c78d070455
commit 49a32e92c1
12 changed files with 315 additions and 60 deletions
@@ -259,6 +259,7 @@ internal fun IrBuiltIns.getKotlinClass(cache: BoxCache): IrClass = when (cache)
BoxCache.LONG -> longClass
}.owner
// TODO: consider adding box caches for unsigned types.
enum class BoxCache {
BOOLEAN, BYTE, SHORT, CHAR, INT, LONG
}
@@ -25,18 +25,16 @@ import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.backend.konan.descriptors.isUnit
import org.jetbrains.kotlin.backend.konan.llvm.*
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.annotations.*
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPublicApi
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.konan.target.*
import org.jetbrains.kotlin.name.isChildOf
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.descriptorUtil.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.isUnit
@@ -760,14 +758,18 @@ internal class CAdapterGenerator(
typedef _Bool ${prefix}_KBoolean;
#endif
""".trimIndent())
output("typedef char ${prefix}_KByte;")
output("typedef unsigned short ${prefix}_KChar;")
output("typedef short ${prefix}_KShort;")
output("typedef int ${prefix}_KInt;")
output("typedef long long ${prefix}_KLong;")
output("typedef float ${prefix}_KFloat;")
output("typedef double ${prefix}_KDouble;")
output("typedef void* ${prefix}_KNativePtr;")
output("typedef unsigned short ${prefix}_KChar;")
output("typedef signed char ${prefix}_KByte;")
output("typedef short ${prefix}_KShort;")
output("typedef int ${prefix}_KInt;")
output("typedef long long ${prefix}_KLong;")
output("typedef unsigned char ${prefix}_KUByte;")
output("typedef unsigned short ${prefix}_KUShort;")
output("typedef unsigned int ${prefix}_KUInt;")
output("typedef unsigned long long ${prefix}_KULong;")
output("typedef float ${prefix}_KFloat;")
output("typedef double ${prefix}_KDouble;")
output("typedef void* ${prefix}_KNativePtr;")
output("struct ${prefix}_KType;")
output("typedef struct ${prefix}_KType ${prefix}_KType;")
@@ -894,6 +896,15 @@ internal class CAdapterGenerator(
}
}
private val unsignedTypeMapping = UnsignedType.values().associate {
it.classId to when (it) {
UnsignedType.UBYTE -> "${prefix}_KUByte"
UnsignedType.USHORT -> "${prefix}_KUShort"
UnsignedType.UINT -> "${prefix}_KUInt"
UnsignedType.ULONG -> "${prefix}_KULong"
}
}
internal fun isMappedToString(descriptor: ClassDescriptor): Boolean =
isMappedToString(descriptor.defaultType.computeBinaryType())
@@ -926,8 +937,10 @@ internal class CAdapterGenerator(
}
private fun translateNonVoidTypeFull(type: KotlinType): Pair<String, String> = type.unwrapToPrimitiveOrReference(
eachInlinedClass = { _, _ ->
// unsigned types to be handled.
eachInlinedClass = { inlinedClass, _ ->
unsignedTypeMapping[inlinedClass.classId]?.let {
return it to it
}
},
ifPrimitive = { primitiveType, _ ->
primitiveTypeMapping[primitiveType]!!.let { it to it }
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.kotlinNativeInternal
import org.jetbrains.kotlin.backend.konan.llvm.findMainEntryPoint
import org.jetbrains.kotlin.backend.konan.lower.TestProcessor
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
import org.jetbrains.kotlin.config.coroutinesPackageFqName
@@ -134,6 +135,14 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
val nativePtr = symbolTable.referenceClass(context.nativePtr)
val nativePtrType = nativePtr.typeWith(arguments = emptyList())
private fun unsignedClass(unsignedType: UnsignedType): IrClassSymbol =
symbolTable.referenceClass(builtIns.builtInsModule.findClassAcrossModuleDependencies(unsignedType.classId)!!)
val uByte = unsignedClass(UnsignedType.UBYTE)
val uShort = unsignedClass(UnsignedType.USHORT)
val uInt = unsignedClass(UnsignedType.UINT)
val uLong = unsignedClass(UnsignedType.ULONG)
val arrayList = symbolTable.referenceClass(getArrayListClassDescriptor(context))
val interopNativePointedGetRawPointer =
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.descriptors.konan.CurrentKonanModuleOrigin
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.types.KotlinType
@@ -95,8 +96,11 @@ internal class ObjCExportCodeGenerator(
): LLVMValueRef = when (valueType) {
ObjCValueType.BOOL -> zext(value, int8Type) // TODO: zext behaviour may be strange on bit types.
ObjCValueType.CHAR, ObjCValueType.UNSIGNED_SHORT, ObjCValueType.SHORT,
ObjCValueType.INT, ObjCValueType.LONG_LONG, ObjCValueType.FLOAT, ObjCValueType.DOUBLE -> value
ObjCValueType.UNICHAR,
ObjCValueType.CHAR, ObjCValueType.SHORT, ObjCValueType.INT, ObjCValueType.LONG_LONG,
ObjCValueType.UNSIGNED_CHAR, ObjCValueType.UNSIGNED_SHORT, ObjCValueType.UNSIGNED_INT,
ObjCValueType.UNSIGNED_LONG_LONG,
ObjCValueType.FLOAT, ObjCValueType.DOUBLE -> value
}
private fun FunctionGenerationContext.objCToKotlin(
@@ -105,8 +109,11 @@ internal class ObjCExportCodeGenerator(
): LLVMValueRef = when (valueType) {
ObjCValueType.BOOL -> icmpNe(value, Int8(0).llvm)
ObjCValueType.CHAR, ObjCValueType.UNSIGNED_SHORT, ObjCValueType.SHORT,
ObjCValueType.INT, ObjCValueType.LONG_LONG, ObjCValueType.FLOAT, ObjCValueType.DOUBLE -> value
ObjCValueType.UNICHAR,
ObjCValueType.CHAR, ObjCValueType.SHORT, ObjCValueType.INT, ObjCValueType.LONG_LONG,
ObjCValueType.UNSIGNED_CHAR, ObjCValueType.UNSIGNED_SHORT, ObjCValueType.UNSIGNED_INT,
ObjCValueType.UNSIGNED_LONG_LONG,
ObjCValueType.FLOAT, ObjCValueType.DOUBLE -> value
}
fun FunctionGenerationContext.kotlinReferenceToObjC(value: LLVMValueRef) =
@@ -340,22 +347,30 @@ private fun ObjCExportCodeGenerator.setObjCExportTypeInfo(
private val ObjCExportCodeGenerator.kotlinToObjCFunctionType: LLVMTypeRef
get() = functionType(int8TypePtr, false, codegen.kObjHeaderPtr)
private fun ObjCExportCodeGenerator.emitBoxConverter(objCValueType: ObjCValueType) {
val symbols = context.ir.symbols
private fun ObjCExportCodeGenerator.emitBoxConverters() {
val irBuiltIns = context.irBuiltIns
val symbols = context.ir.symbols
val boxClass = when (objCValueType) {
ObjCValueType.BOOL -> irBuiltIns.booleanClass
ObjCValueType.UNSIGNED_SHORT -> irBuiltIns.charClass
ObjCValueType.CHAR -> irBuiltIns.byteClass
ObjCValueType.SHORT -> irBuiltIns.shortClass
ObjCValueType.INT -> irBuiltIns.intClass
ObjCValueType.LONG_LONG -> irBuiltIns.longClass
ObjCValueType.FLOAT -> irBuiltIns.floatClass
ObjCValueType.DOUBLE -> irBuiltIns.doubleClass
}.owner
emitBoxConverter(irBuiltIns.booleanClass, ObjCValueType.BOOL, "numberWithBool:")
emitBoxConverter(irBuiltIns.byteClass, ObjCValueType.CHAR, "numberWithChar:")
emitBoxConverter(irBuiltIns.shortClass, ObjCValueType.SHORT, "numberWithShort:")
emitBoxConverter(irBuiltIns.intClass, ObjCValueType.INT, "numberWithInt:")
emitBoxConverter(irBuiltIns.longClass, ObjCValueType.LONG_LONG, "numberWithLongLong:")
emitBoxConverter(symbols.uByte, ObjCValueType.UNSIGNED_CHAR, "numberWithUnsignedChar")
emitBoxConverter(symbols.uShort, ObjCValueType.UNSIGNED_SHORT, "numberWithUnsignedShort:")
emitBoxConverter(symbols.uInt, ObjCValueType.UNSIGNED_INT, "numberWithUnsignedInt:")
emitBoxConverter(symbols.uLong, ObjCValueType.UNSIGNED_LONG_LONG, "numberWithUnsignedLongLong:")
emitBoxConverter(irBuiltIns.floatClass, ObjCValueType.FLOAT, "numberWithFloat:")
emitBoxConverter(irBuiltIns.doubleClass, ObjCValueType.DOUBLE, "numberWithDouble:")
}
val name = "${boxClass.name}To${objCValueType.nsNumberName}"
private fun ObjCExportCodeGenerator.emitBoxConverter(
boxClassSymbol: IrClassSymbol,
objCValueType: ObjCValueType,
nsNumberFactorySelector: String
) {
val boxClass = boxClassSymbol.owner
val name = "${boxClass.name}ToNSNumber"
val converter = generateFunction(codegen, kotlinToObjCFunctionType, name) {
val unboxFunction = context.getUnboxFunction(boxClass).llvmFunction
@@ -368,7 +383,7 @@ private fun ObjCExportCodeGenerator.emitBoxConverter(objCValueType: ObjCValueTyp
val value = kotlinToObjC(kotlinValue, objCValueType)
val nsNumber = genGetSystemClass("NSNumber")
ret(genSendMessage(int8TypePtr, nsNumber, objCValueType.nsNumberFactorySelector, value))
ret(genSendMessage(int8TypePtr, nsNumber, nsNumberFactorySelector, value))
}
LLVMSetLinkage(converter, LLVMLinkage.LLVMPrivateLinkage)
@@ -446,9 +461,7 @@ private fun ObjCExportCodeGenerator.emitSpecialClassesConvertions() {
constPointer(context.llvm.Kotlin_Interop_CreateKotlinMutableDictonaryFromKMap)
)
ObjCValueType.values().forEach {
emitBoxConverter(it)
}
emitBoxConverters()
emitFunctionConverters()
@@ -1091,11 +1104,15 @@ private fun objCFunctionType(context: Context, methodBridge: MethodBridge): LLVM
private val ObjCValueType.llvmType: LLVMTypeRef get() = when (this) {
ObjCValueType.BOOL -> int8Type
ObjCValueType.UNICHAR -> int16Type
ObjCValueType.CHAR -> int8Type
ObjCValueType.UNSIGNED_SHORT -> int16Type
ObjCValueType.SHORT -> int16Type
ObjCValueType.INT -> int32Type
ObjCValueType.LONG_LONG -> int64Type
ObjCValueType.UNSIGNED_CHAR -> int8Type
ObjCValueType.UNSIGNED_SHORT -> int16Type
ObjCValueType.UNSIGNED_INT -> int32Type
ObjCValueType.UNSIGNED_LONG_LONG -> int64Type
ObjCValueType.FLOAT -> LLVMFloatType()!!
ObjCValueType.DOUBLE -> LLVMDoubleType()!!
}
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.konan.objcexport
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.descriptors.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
@@ -66,13 +67,18 @@ abstract class ObjCExportHeaderGenerator(
result += CustomTypeMapper.Collection(generator, map, "NSDictionary")
result += CustomTypeMapper.Collection(generator, mutableMap, namer.mutableMapName)
for (descriptor in listOf(boolean, char, byte, short, int, long, float, double)) {
for (descriptor in listOf(boolean, byte, short, int, long, float, double)) {
// TODO: Kotlin code doesn't have any checkcasts on unboxing,
// so it is possible that it expects boxed number of other type and unboxes it incorrectly.
// TODO: NSNumber seem to have different equality semantics.
result += CustomTypeMapper.Simple(descriptor, "NSNumber")
}
for (unsignedType in UnsignedType.values()) {
val descriptor = moduleDescriptor.findClassAcrossModuleDependencies(unsignedType.classId)!!
result += CustomTypeMapper.Simple(descriptor, "NSNumber")
}
result += CustomTypeMapper.Simple(string, "NSString")
(0..mapper.maxFunctionTypeParameterCount).forEach {
@@ -737,11 +743,15 @@ abstract class ObjCExportHeaderGenerator(
is ValueTypeBridge -> {
val cName = when (typeBridge.objCValueType) {
ObjCValueType.BOOL -> "BOOL"
ObjCValueType.UNICHAR -> "unichar"
ObjCValueType.CHAR -> "int8_t"
ObjCValueType.UNSIGNED_SHORT -> "unichar"
ObjCValueType.SHORT -> "int16_t"
ObjCValueType.INT -> "int32_t"
ObjCValueType.LONG_LONG -> "int64_t"
ObjCValueType.UNSIGNED_CHAR -> "uint8_t"
ObjCValueType.UNSIGNED_SHORT -> "uint16_t"
ObjCValueType.UNSIGNED_INT -> "uint32_t"
ObjCValueType.UNSIGNED_LONG_LONG -> "uint64_t"
ObjCValueType.FLOAT -> "float"
ObjCValueType.DOUBLE -> "double"
}
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenDescriptors
import org.jetbrains.kotlin.backend.konan.descriptors.isArray
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.resolve.descriptorUtil.*
import org.jetbrains.kotlin.types.KotlinType
@@ -111,13 +112,18 @@ internal fun ObjCExportMapper.doesThrow(method: FunctionDescriptor): Boolean = m
}
private fun ObjCExportMapper.bridgeType(kotlinType: KotlinType): TypeBridge = kotlinType.unwrapToPrimitiveOrReference(
eachInlinedClass = { _, _ ->
// unsigned types to be handled.
eachInlinedClass = { inlinedClass, _ ->
when (inlinedClass.classId) {
UnsignedType.UBYTE.classId -> return ValueTypeBridge(ObjCValueType.UNSIGNED_CHAR)
UnsignedType.USHORT.classId -> return ValueTypeBridge(ObjCValueType.UNSIGNED_SHORT)
UnsignedType.UINT.classId -> return ValueTypeBridge(ObjCValueType.UNSIGNED_INT)
UnsignedType.ULONG.classId -> return ValueTypeBridge(ObjCValueType.UNSIGNED_LONG_LONG)
}
},
ifPrimitive = { primitiveType, _ ->
val objCValueType = when (primitiveType) {
KonanPrimitiveType.BOOLEAN -> ObjCValueType.BOOL
KonanPrimitiveType.CHAR -> ObjCValueType.UNSIGNED_SHORT
KonanPrimitiveType.CHAR -> ObjCValueType.UNICHAR
KonanPrimitiveType.BYTE -> ObjCValueType.CHAR
KonanPrimitiveType.SHORT -> ObjCValueType.SHORT
KonanPrimitiveType.INT -> ObjCValueType.INT
@@ -219,4 +225,4 @@ internal fun ObjCExportMapper.bridgePropertyType(descriptor: PropertyDescriptor)
assert(isBaseProperty(descriptor))
return bridgeType(descriptor.type)
}
}
@@ -111,27 +111,17 @@ object ObjCVoidType : ObjCType() {
override fun render(attrsAndName: String) = "void".withAttrsAndName(attrsAndName)
}
internal enum class ObjCValueType(
val encoding: String
) {
internal enum class ObjCValueType(val encoding: String) {
BOOL("c"),
UNICHAR("S"),
CHAR("c"),
SHORT("s"),
UNSIGNED_SHORT("S"),
INT("i"),
LONG_LONG("q"),
UNSIGNED_CHAR("C"),
UNSIGNED_SHORT("S"),
UNSIGNED_INT("I"),
UNSIGNED_LONG_LONG("Q"),
FLOAT("f"),
DOUBLE("d")
;
// UNSIGNED_SHORT -> unsignedShort
val nsNumberName = this.name.split('_').mapIndexed { index, s ->
val lower = s.toLowerCase()
if (index > 0) lower.capitalize() else lower
}.joinToString("")
val nsNumberValueSelector get() = "${nsNumberName}Value"
val nsNumberFactorySelector get() = "numberWith${nsNumberName.capitalize()}:"
}
+8 -2
View File
@@ -433,11 +433,14 @@ static void initializeObjCExport() {
extern "C" {
OBJ_GETTER(Kotlin_boxBoolean, KBoolean value);
OBJ_GETTER(Kotlin_boxChar, KChar value);
OBJ_GETTER(Kotlin_boxByte, KByte value);
OBJ_GETTER(Kotlin_boxShort, KShort value);
OBJ_GETTER(Kotlin_boxInt, KInt value);
OBJ_GETTER(Kotlin_boxLong, KLong value);
OBJ_GETTER(Kotlin_boxUByte, KUByte value);
OBJ_GETTER(Kotlin_boxUShort, KUShort value);
OBJ_GETTER(Kotlin_boxUInt, KUInt value);
OBJ_GETTER(Kotlin_boxULong, KULong value);
OBJ_GETTER(Kotlin_boxFloat, KFloat value);
OBJ_GETTER(Kotlin_boxDouble, KDouble value);
@@ -457,11 +460,14 @@ static OBJ_GETTER(boxedBooleanToKotlinImp, NSNumber* self, SEL cmd) {
// TODO: the code below makes some assumption on char, short, int and long sizes.
switch (type[0]) {
case 'S': RETURN_RESULT_OF(Kotlin_boxChar, self.unsignedShortValue);
case 'c': RETURN_RESULT_OF(Kotlin_boxByte, self.charValue);
case 's': RETURN_RESULT_OF(Kotlin_boxShort, self.shortValue);
case 'i': RETURN_RESULT_OF(Kotlin_boxInt, self.intValue);
case 'q': RETURN_RESULT_OF(Kotlin_boxLong, self.longLongValue);
case 'C': RETURN_RESULT_OF(Kotlin_boxUByte, self.unsignedCharValue);
case 'S': RETURN_RESULT_OF(Kotlin_boxUShort, self.unsignedShortValue);
case 'I': RETURN_RESULT_OF(Kotlin_boxUInt, self.unsignedIntValue);
case 'Q': RETURN_RESULT_OF(Kotlin_boxULong, self.unsignedLongLongValue);
case 'f': RETURN_RESULT_OF(Kotlin_boxFloat, self.floatValue);
case 'd': RETURN_RESULT_OF(Kotlin_boxDouble, self.doubleValue);
+4
View File
@@ -42,6 +42,10 @@ typedef uint16_t KChar;
typedef int16_t KShort;
typedef int32_t KInt;
typedef int64_t KLong;
typedef uint8_t KUByte;
typedef uint16_t KUShort;
typedef uint32_t KUInt;
typedef uint64_t KULong;
typedef float KFloat;
typedef double KDouble;
typedef void* KNativePtr;
@@ -237,6 +237,29 @@ external private fun copyImpl(array: IntArray, fromIndex: Int,
external private fun copyImpl(array: LongArray, fromIndex: Int,
destination: LongArray, toIndex: Int, count: Int)
// Note: [copyImpl] for an unsigned array is bitwise identical to signed type, so
// signed array implementations from runtime are directly reused for unsigned ones.
@ExperimentalUnsignedTypes
@SymbolName("Kotlin_ByteArray_copyImpl")
external private fun copyImpl(array: UByteArray, fromIndex: Int,
destination: UByteArray, toIndex: Int, count: Int)
@ExperimentalUnsignedTypes
@SymbolName("Kotlin_ShortArray_copyImpl")
external private fun copyImpl(array: UShortArray, fromIndex: Int,
destination: UShortArray, toIndex: Int, count: Int)
@ExperimentalUnsignedTypes
@SymbolName("Kotlin_IntArray_copyImpl")
external private fun copyImpl(array: UIntArray, fromIndex: Int,
destination: UIntArray, toIndex: Int, count: Int)
@ExperimentalUnsignedTypes
@SymbolName("Kotlin_LongArray_copyImpl")
external private fun copyImpl(array: ULongArray, fromIndex: Int,
destination: ULongArray, toIndex: Int, count: Int)
@SymbolName("Kotlin_FloatArray_copyImpl")
external private fun copyImpl(array: FloatArray, fromIndex: Int,
destination: FloatArray, toIndex: Int, count: Int)
@@ -279,6 +302,30 @@ fun LongArray.copyRangeTo(destination: LongArray, fromIndex: Int, toIndex: Int,
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
}
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
fun UByteArray.copyRangeTo(destination: UByteArray, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) {
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
}
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
fun UShortArray.copyRangeTo(destination: UShortArray, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) {
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
}
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
fun UIntArray.copyRangeTo(destination: UIntArray, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) {
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
}
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
fun ULongArray.copyRangeTo(destination: ULongArray, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) {
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
}
fun FloatArray.copyRangeTo(destination: FloatArray, fromIndex: Int, toIndex: Int, destinationIndex: Int = 0) {
copyImpl(this, fromIndex, destination, destinationIndex, toIndex - fromIndex)
}
@@ -514,6 +514,94 @@ public actual fun LongArray.contentToString(): String {
}
}
/**
* Returns a string representation of the contents of the specified array as if it is [List].
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun UByteArray.contentToString(): String {
if (size == 0)
return "[]"
val iMax = size - 1
val b = StringBuilder()
b.append('[')
var i = 0
while (true) {
b.append(this[i])
if (i == iMax)
return b.append(']').toString()
b.append(", ")
i++
}
}
/**
* Returns a string representation of the contents of the specified array as if it is [List].
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun UShortArray.contentToString(): String {
if (size == 0)
return "[]"
val iMax = size - 1
val b = StringBuilder()
b.append('[')
var i = 0
while (true) {
b.append(this[i])
if (i == iMax)
return b.append(']').toString()
b.append(", ")
i++
}
}
/**
* Returns a string representation of the contents of the specified array as if it is [List].
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun UIntArray.contentToString(): String {
if (size == 0)
return "[]"
val iMax = size - 1
val b = StringBuilder()
b.append('[')
var i = 0
while (true) {
b.append(this[i])
if (i == iMax)
return b.append(']').toString()
b.append(", ")
i++
}
}
/**
* Returns a string representation of the contents of the specified array as if it is [List].
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun ULongArray.contentToString(): String {
if (size == 0)
return "[]"
val iMax = size - 1
val b = StringBuilder()
b.append('[')
var i = 0
while (true) {
b.append(this[i])
if (i == iMax)
return b.append(']').toString()
b.append(", ")
i++
}
}
/**
* Returns a string representation of the contents of the specified array as if it is [List].
*/
@@ -972,6 +1060,54 @@ public actual fun LongArray.contentHashCode(): Int {
return result
}
/**
* Returns a hash code based on the contents of this array as if it is [List].
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun UByteArray.contentHashCode(): Int {
var result = 1
for (element in this)
result = 31 * result + element.hashCode()
return result
}
/**
* Returns a hash code based on the contents of this array as if it is [List].
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun UShortArray.contentHashCode(): Int {
var result = 1
for (element in this)
result = 31 * result + element.hashCode()
return result
}
/**
* Returns a hash code based on the contents of this array as if it is [List].
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun UIntArray.contentHashCode(): Int {
var result = 1
for (element in this)
result = 31 * result + element.hashCode()
return result
}
/**
* Returns a hash code based on the contents of this array as if it is [List].
*/
@SinceKotlin("1.3")
@ExperimentalUnsignedTypes
public fun ULongArray.contentHashCode(): Int {
var result = 1
for (element in this)
result = 31 * result + element.hashCode()
return result
}
/**
* Returns a hash code based on the contents of this array as if it is [List].
*/
@@ -61,6 +61,22 @@ fun boxInt(value: Int): Int? = value
@ExportForCppRuntime("Kotlin_boxLong")
fun boxLong(value: Long): Long? = value
@ExperimentalUnsignedTypes
@ExportForCppRuntime("Kotlin_boxUByte")
fun boxUByte(value: UByte): UByte? = value
@ExperimentalUnsignedTypes
@ExportForCppRuntime("Kotlin_boxUShort")
fun boxUShort(value: UShort): UShort? = value
@ExperimentalUnsignedTypes
@ExportForCppRuntime("Kotlin_boxUInt")
fun boxUInt(value: UInt): UInt? = value
@ExperimentalUnsignedTypes
@ExportForCppRuntime("Kotlin_boxULong")
fun boxULong(value: ULong): ULong? = value
@ExportForCppRuntime("Kotlin_boxFloat")
fun boxFloat(value: Float): Float? = value