From 64998a825efdeaf65351e56f0c91d9ea44df717d Mon Sep 17 00:00:00 2001 From: crc-32 Date: Wed, 20 Oct 2021 00:09:19 +0100 Subject: [PATCH] Implement/fix iOS native DataBuffer properly --- gradle.properties | 2 +- src/iosMain/kotlin/util/DataBuffer.kt | 57 +++++++++++++----------- src/iosMain/kotlin/util/UtilFunctions.kt | 19 +++++++- 3 files changed, 51 insertions(+), 27 deletions(-) diff --git a/gradle.properties b/gradle.properties index af3db2f..34b5d40 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,4 +2,4 @@ kotlin.code.style=official group=io.rebble.libpebblecommon version=0.0.25 -org.gradle.jvmargs=-Xms1G \ No newline at end of file +org.gradle.jvmargs=-Xms2G -Xmx2G \ No newline at end of file diff --git a/src/iosMain/kotlin/util/DataBuffer.kt b/src/iosMain/kotlin/util/DataBuffer.kt index c12277a..2acbc79 100644 --- a/src/iosMain/kotlin/util/DataBuffer.kt +++ b/src/iosMain/kotlin/util/DataBuffer.kt @@ -22,47 +22,55 @@ actual class DataBuffer { get() = _readPosition actual constructor(size: Int) { - actualBuf = NSMutableData.dataWithLength(size.toULong())!! - actualBuf.setLength(size.toULong()) + actualBuf = NSMutableData.dataWithCapacity(size.toULong())!! } actual constructor(bytes: UByteArray) { actualBuf = NSMutableData() - actualBuf.setData( - NSString.create(string = bytes.toString()) - .dataUsingEncoding(NSUTF8StringEncoding, false)!! - ) + memScoped { + actualBuf.setData( + NSData.create(bytes = allocArrayOf(bytes.toByteArray()), length = bytes.size.toULong()) + ) + } + } + + private fun shouldReverse(): Boolean { + return if (isPlatformBigEndian() && !littleEndian) { + false + }else if (isPlatformBigEndian() && littleEndian) { + true + }else !isPlatformBigEndian() && !littleEndian } actual fun putUShort(short: UShort) { memScoped { val pShort = alloc() - pShort.value = short + pShort.value = if (shouldReverse()) reverseOrd(short) else short actualBuf.appendBytes(pShort.ptr, UShort.SIZE_BYTES.toULong()) } } actual fun getUShort(): UShort { memScoped { val pShort = alloc() - actualBuf.getBytes(pShort.ptr, UShort.SIZE_BYTES.toULong()) + actualBuf.getBytes(pShort.ptr, NSMakeRange(_readPosition.toULong(), UShort.SIZE_BYTES.toULong())) _readPosition += UShort.SIZE_BYTES - return pShort.value + return if (shouldReverse()) reverseOrd(pShort.value) else pShort.value } } actual fun putShort(short: Short) { memScoped { val pShort = alloc() - pShort.value = short + pShort.value = if (shouldReverse()) reverseOrd(short.toUShort()).toShort() else short actualBuf.appendBytes(pShort.ptr, Short.SIZE_BYTES.toULong()) } } actual fun getShort(): Short { memScoped { val pShort = alloc() - actualBuf.getBytes(pShort.ptr, Short.SIZE_BYTES.toULong()) + actualBuf.getBytes(pShort.ptr, NSMakeRange(_readPosition.toULong(), Short.SIZE_BYTES.toULong())) _readPosition += Short.SIZE_BYTES - return pShort.value + return if (shouldReverse()) reverseOrd(pShort.value.toUShort()).toShort() else pShort.value } } @@ -76,7 +84,7 @@ actual class DataBuffer { actual fun getUByte(): UByte { memScoped { val pByte = alloc() - actualBuf.appendBytes(pByte.ptr, UByte.SIZE_BYTES.toULong()) + actualBuf.getBytes(pByte.ptr, NSMakeRange(_readPosition.toULong(), UByte.SIZE_BYTES.toULong())) _readPosition += UByte.SIZE_BYTES return pByte.value } @@ -92,7 +100,7 @@ actual class DataBuffer { actual fun getByte(): Byte { memScoped { val pByte = alloc() - actualBuf.appendBytes(pByte.ptr, Byte.SIZE_BYTES.toULong()) + actualBuf.getBytes(pByte.ptr, NSMakeRange(_readPosition.toULong(), Byte.SIZE_BYTES.toULong())) _readPosition += Byte.SIZE_BYTES return pByte.value } @@ -107,7 +115,7 @@ actual class DataBuffer { actual fun getBytes(count: Int): UByteArray { memScoped { val pBytes = allocArray(count) - actualBuf.getBytes(pBytes.getPointer(this), length = count.toULong()) + actualBuf.getBytes(pBytes.getPointer(this), NSMakeRange(_readPosition.toULong(), count.toULong())) _readPosition += count return pBytes.readBytes(count).toUByteArray() } @@ -117,54 +125,53 @@ actual class DataBuffer { actual fun setEndian(endian: Char) { littleEndian = endian == '<' - if (littleEndian) TODO("iOS little endian") } actual fun putUInt(uint: UInt) { memScoped { val pUInt = alloc() - pUInt.value = uint + pUInt.value = if (shouldReverse()) reverseOrd(uint) else uint actualBuf.appendBytes(pUInt.ptr, UInt.SIZE_BYTES.toULong()) } } actual fun getUInt(): UInt { memScoped { val pUInt = alloc() - actualBuf.getBytes(pUInt.ptr, UInt.SIZE_BYTES.toULong()) + actualBuf.getBytes(pUInt.ptr, NSMakeRange(_readPosition.toULong(), UInt.SIZE_BYTES.toULong())) _readPosition += UInt.SIZE_BYTES - return pUInt.value + return if (shouldReverse()) reverseOrd(pUInt.value) else pUInt.value } } actual fun putInt(int: Int) { memScoped { val pInt = alloc() - pInt.value = int + pInt.value = if (shouldReverse()) reverseOrd(int.toUInt()).toInt() else int actualBuf.appendBytes(pInt.ptr, Int.SIZE_BYTES.toULong()) } } actual fun getInt(): Int { memScoped { val pInt = alloc() - actualBuf.getBytes(pInt.ptr, Int.SIZE_BYTES.toULong()) + actualBuf.getBytes(pInt.ptr, NSMakeRange(_readPosition.toULong(), Int.SIZE_BYTES.toULong())) _readPosition += Int.SIZE_BYTES - return pInt.value + return if (shouldReverse()) reverseOrd(pInt.value.toUInt()).toInt() else pInt.value } } actual fun putULong(ulong: ULong) { memScoped { val pULong = alloc() - pULong.value = ulong + pULong.value = if (shouldReverse()) reverseOrd(ulong) else ulong actualBuf.appendBytes(pULong.ptr, ULong.SIZE_BYTES.toULong()) } } actual fun getULong(): ULong { memScoped { val pULong = alloc() - actualBuf.getBytes(pULong.ptr, ULong.SIZE_BYTES.toULong()) + actualBuf.getBytes(pULong.ptr, NSMakeRange(_readPosition.toULong(), ULong.SIZE_BYTES.toULong())) _readPosition += ULong.SIZE_BYTES - return pULong.value + return if (shouldReverse()) reverseOrd(pULong.value) else pULong.value } } diff --git a/src/iosMain/kotlin/util/UtilFunctions.kt b/src/iosMain/kotlin/util/UtilFunctions.kt index 9319f8c..44abe29 100644 --- a/src/iosMain/kotlin/util/UtilFunctions.kt +++ b/src/iosMain/kotlin/util/UtilFunctions.kt @@ -1,3 +1,20 @@ package io.rebble.libpebblecommon.util -actual fun runBlocking(block: suspend () -> Unit) = kotlinx.coroutines.runBlocking{block()} \ No newline at end of file +import kotlinx.cinterop.* + +actual fun runBlocking(block: suspend () -> Unit) = kotlinx.coroutines.runBlocking{block()} + +internal fun isPlatformBigEndian(): Boolean { + memScoped { + val i = alloc() + i.value = 1 + val bytes = i.reinterpret() + return bytes.value == 0.toByte() + } +} + +internal fun reverseOrd(varr: UShort): UShort = (((varr.toInt() and 0xff) shl 8) or ((varr.toInt() and 0xffff) ushr 8)).toUShort() + +internal fun reverseOrd(varr: UInt): UInt = ((reverseOrd((varr and 0xffffu).toUShort()).toInt() shl 16) or (reverseOrd((varr shr 16).toUShort()).toInt() and 0xffff)).toUInt() + +internal fun reverseOrd(varr: ULong): ULong = ((reverseOrd((varr and 0xffffffffu).toUInt()).toLong() shl 32) or (reverseOrd((varr shr 32).toUInt()).toLong() and 0xffffffff)).toULong() \ No newline at end of file