Could someone help me out with converting this C# code to Kotlin?
public static UInt32 CalculdateCrc32(byte[] bytes, int length)
{
UInt32 Checksum = 0xFFFFFFFF;
for (int i = 0; i < length; i++)
{
byte top = (byte)(Checksum >> 24);
top ^= bytes[i];
Checksum = (Checksum << 8) ^ crc_table[top];
}
return Checksum;
}
It allows the CRC32 caluclation of the first length
bytes of bytes
.
I have tried different approaches to deal with the unsigned datatypes, but I cannot get it to return the correct CRC.
private val crcTable = (0 until 256).map {
crc32(it.toUByte(), 0x04C11DB7.toUInt())
}
private fun crc32(input: UByte, polynomial: UInt): UInt {
val bigEndianInput = input.toBigEndianUInt()
return (0 until 8).fold(bigEndianInput) { result, _ ->
val isMostSignificantBitOne = result and 0x80000000.toUInt() != 0.toUInt()
val shiftedResult = result shl 1
when (isMostSignificantBitOne) {
true -> shiftedResult xor polynomial
false -> shiftedResult
}
}
}
private fun UByte.toBigEndianUInt(): UInt = this.toUInt() shl 24
private fun calculateCrc32(bytes: ByteArray, length: Int): UInt {
var checksum : UInt = 0xFFFFFFFFu
for (i in 0 until length) {
var top = (checksum shr 24).toByte()
top = top xor bytes[i]
checksum = checksum shl 8 xor crcTable[top.toInt()]
}
return checksum
}
But this code throws an IndexOutOfBoundsException, because top
ends up being -1.
class CrcUtilTest {
@Test
fun crc16_correctByteArray_returnsCorrectCrc16() {
val data = byteArrayOf(
0xaa.toByte(),
0xbb.toByte(),
0xcc.toByte(),
0xdd.toByte(),
0xaa.toByte(),
0xbb.toByte(),
0xcc.toByte(),
0xdd.toByte(),
0xaa.toByte(),
0xbb.toByte(),
0xcc.toByte(),
0xdd.toByte(),
0xaa.toByte(),
0xaa.toByte(),
0xbb.toByte()
)
CrcUtil.updateCrc16(data)
assertThat(data[13]).isEqualTo(0xaa)
assertThat(data[14]).isEqualTo(0xbb)
}
}
Try toUByte()
instead of toByte()
in calcCrc32()
, also applying it to the result of bytes[i]
.
private fun calcCrc32(bytes: ByteArray, length: Int): UInt {
var checksum: UInt = 0xFFFFFFFFu
val uBytes = bytes.toUByteArray()
for (i in 0 until length) {
var top = (checksum shr 24).toUByte()
top = top xor uBytes[i]
checksum = checksum shl 8 xor crcTable[top.toInt()]
}
return checksum
}