Last active
April 24, 2024 08:41
-
-
Save fabiomsr/845664a9c7e92bafb6fb0ca70d4e44fd to your computer and use it in GitHub Desktop.
ByteArray and String extension to add hexadecimal methods in Kotlin
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private val HEX_CHARS = "0123456789ABCDEF".toCharArray() | |
fun ByteArray.toHex() : String{ | |
val result = StringBuffer() | |
forEach { | |
val octet = it.toInt() | |
val firstIndex = (octet and 0xF0).ushr(4) | |
val secondIndex = octet and 0x0F | |
result.append(HEX_CHARS[firstIndex]) | |
result.append(HEX_CHARS[secondIndex]) | |
} | |
return result.toString() | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private val HEX_CHARS = "0123456789ABCDEF" | |
fun String.hexStringToByteArray() : ByteArray { | |
val result = ByteArray(length / 2) | |
for (i in 0 until length step 2) { | |
val firstIndex = HEX_CHARS.indexOf(this[i]); | |
val secondIndex = HEX_CHARS.indexOf(this[i + 1]); | |
val octet = firstIndex.shl(4).or(secondIndex) | |
result.set(i.shr(1), octet.toByte()) | |
} | |
return result | |
} |
recover test
@Test
fun fromHEX() {
val hex = "7a7a687ae4b8ade58d88"
val f1 = { hex.chunked(2).map { it.toInt(16).toByte() }.toByteArray() }
val f2 = {
val len = hex.length
val result = ByteArray(len / 2)
for (i in 0 until len step 2) {
val firstIndex = HEX_CHARS.indexOf(hex[i])
val secondIndex = HEX_CHARS.indexOf(hex[i + 1])
val octet = firstIndex.shl(4).or(secondIndex)
result[i.shr(1)] = octet.toByte()
}
result
}
val f3 = {
val len = hex.length
val result = ByteArray(len / 2)
(0 until len step 2).forEach { i ->
val firstIndex = HEX_CHARS.indexOf(hex[i])
val secondIndex = HEX_CHARS.indexOf(hex[i + 1])
val octet = firstIndex.shl(4).or(secondIndex)
result[i.shr(1)] = octet.toByte()
}
result
}
val f4 = {
val len = hex.length
val result = ByteArray(len / 2)
(0 until len step 2).forEach { i ->
result[i.shr(1)] = HEX_CHARS.indexOf(hex[i]).shl(4).or(HEX_CHARS.indexOf(hex[i + 1])).toByte()
}
result
}
val f5 = {
(hex.indices step 2).map { i ->
HEX_CHARS.indexOf(hex[i]).shl(4).or(HEX_CHARS.indexOf(hex[i + 1])).toByte()
}.toByteArray()
}
f1().apply(print)
f2().apply(print)
f3().apply(print)
f4().apply(print)
f5().apply(print)
mapOf(
"f1" to f1
, "f2" to f2
, "f3" to f3
, "f4" to f4
, "f5" to f5
).forEach { o, a -> measureOp(o, a) }
}
f1: 0.480646209 ms/op
f2: 0.126997772 ms/op
f3: 0.113088663 ms/op
f4: 0.098126381 ms/op
f5: 0.201921568 ms/op
For people commenting alternatives to the gist, bear in mind that the gist is in Kotlin. The API does not have String.format
, as this is from the Kotlin JVM lib. The posted examples won't work in Kotlin Native.
For people commenting alternatives to the gist, bear in mind that the gist is in Kotlin. The API does not have
String.format
, as this is from the Kotlin JVM lib. The posted examples won't work in Kotlin Native.
source.joinToString("") { it.toInt().and(0xff).toString(16).padStart(2, '0') }
works with Kotlin/Native at least for the targets JVM, Android, iOS & macOS as expected
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@gmk57
a full testing
and result show
current speed winner is
and avg winner is