175 lines
5.0 KiB
Kotlin
175 lines
5.0 KiB
Kotlin
package net.sergeych.bintools
|
|
|
|
|
|
fun longToBytes(value: Long): ByteArray {
|
|
var l = value
|
|
val result = ByteArray(8)
|
|
for (i in 7 downTo 0) {
|
|
result[i] = (l and 0xFF).toByte()
|
|
l = l shr 8
|
|
}
|
|
return result
|
|
}
|
|
|
|
fun intToBytes(value: Int): ByteArray {
|
|
var l = value
|
|
val result = ByteArray(8)
|
|
for (i in 3 downTo 0) {
|
|
result[i] = (l and 0xFF).toByte()
|
|
l = l shr 8
|
|
}
|
|
return result
|
|
}
|
|
|
|
fun uintToBytes(value: UInt): ByteArray {
|
|
var l = value
|
|
val result = ByteArray(4)
|
|
for (i in 3 downTo 0) {
|
|
result[i] = (l and 0xFFu).toByte()
|
|
l = l shr 8
|
|
}
|
|
return result
|
|
}
|
|
|
|
/**
|
|
* Convert 8 bytes to LE long
|
|
*/
|
|
fun bytesToLong(b: ByteArray): Long {
|
|
var result: Long = 0
|
|
for (i in 0 until 8) {
|
|
result = result shl 8
|
|
result = result or (b[i].toLong() and 0xFF)
|
|
}
|
|
return result
|
|
}
|
|
|
|
fun bytesToInt(b: ByteArray): Int {
|
|
var result: Int = 0
|
|
for (i in 0 until 4) {
|
|
result = result shl 8
|
|
result = result or (b[i].toInt() and 0xFF)
|
|
}
|
|
return result
|
|
}
|
|
|
|
fun bytesToUInt(b: ByteArray): UInt {
|
|
var result = 0u
|
|
for (i in 0 until 4) {
|
|
result = result shl 8
|
|
result = result or (b[i].toUInt() and 0xFFu)
|
|
}
|
|
return result
|
|
}
|
|
|
|
|
|
private val hexDigits = "0123456789ABCDEF"
|
|
|
|
fun Long.encodeToHex(length: Int = 0): String {
|
|
var result = ""
|
|
var value = this
|
|
var end = if( value >= 0 ) 0L else -1L
|
|
// if (value < 0) throw IllegalArgumentException("cant convert to hex negative (ambiguous)")
|
|
do {
|
|
result = hexDigits[(value and 0x0f).toInt()] + result
|
|
value = value shr 4
|
|
} while (value != end)
|
|
while (result.length < length) result = "0" + result
|
|
return result
|
|
}
|
|
|
|
fun Int.encodeToHex(length: Int = 0) = (toLong() and 0xFFFFffff).encodeToHex(length)
|
|
@Suppress("unused")
|
|
fun UInt.encodeToHex(length: Int = 0) = toLong().encodeToHex(length)
|
|
fun Byte.encodeToHex(length: Int = 0) = (toLong() and 0xFF).encodeToHex(length)
|
|
fun UByte.encodeToHex(length: Int = 0) = toLong().encodeToHex(length)
|
|
@Suppress("unused")
|
|
fun ULong.encodeToHex(length: Int = 0) = toLong().encodeToHex(length)
|
|
|
|
fun ByteArray.encodeToHex(separator: String = " "): String = joinToString(separator) { it.toUByte().encodeToHex(2) }
|
|
fun Collection<Byte>.encodeToHex(separator: String = " "): String = joinToString(separator) { it.toUByte().encodeToHex(2) }
|
|
|
|
fun ByteArray.toDump(wide: Boolean = false): String = toDumpLines(wide).joinToString("\n")
|
|
|
|
fun ByteArray.toDumpLines(wide: Boolean = false): List<String> {
|
|
|
|
val lineSize = if (wide) 32 else 16
|
|
|
|
fun dumpChars(_from: Int): String {
|
|
var from = _from
|
|
val b = StringBuilder(22)
|
|
|
|
b.append('|')
|
|
val max: Int = kotlin.math.min(size, from + lineSize)
|
|
while (from < max) {
|
|
val ch = this[from++].toInt()
|
|
if (ch >= ' '.code && ch < 127) b.append(ch.toChar()) else b.append('.')
|
|
}
|
|
val remainder = from % lineSize
|
|
if (remainder > 0) {
|
|
var cnt = lineSize - remainder
|
|
while (cnt-- > 0) b.append(' ')
|
|
}
|
|
return b.append("|").toString()
|
|
}
|
|
|
|
|
|
val lines = mutableListOf<String>()
|
|
if (size == 0) return lines
|
|
var line: StringBuilder? = null
|
|
|
|
if (size != 0) {
|
|
for (i in indices) {
|
|
if (i % lineSize == 0) {
|
|
if (line != null) {
|
|
line.append(dumpChars(i - lineSize))
|
|
lines.add(line.toString())
|
|
}
|
|
line = StringBuilder(i.encodeToHex(4))
|
|
line.append(' ')
|
|
}
|
|
line!!.append((this[i].toUByte()).encodeToHex(2))
|
|
line.append(' ')
|
|
}
|
|
if (line != null) {
|
|
val l = size
|
|
var fill = lineSize - l % lineSize
|
|
if (fill < lineSize) while (fill-- > 0) line.append(" ")
|
|
val index = l - l % lineSize
|
|
line.append(dumpChars(if (index < l) index else l - lineSize))
|
|
lines.add(line.toString())
|
|
}
|
|
}
|
|
return lines
|
|
}
|
|
|
|
fun String.decodeHex(): ByteArray {
|
|
val source = this.trim().uppercase()
|
|
val result = arrayListOf<Byte>()
|
|
var pos = 0
|
|
while (pos < source.length) {
|
|
val i = hexDigits.indexOf(source[pos++])
|
|
if (i < 0) throw FormatException("invalid hex digit in ${source} at ${pos - 1}")
|
|
if (pos >= source.length) throw FormatException(
|
|
"hex string must consist of bytes " +
|
|
"(unexepced end of data): $source"
|
|
)
|
|
val j = hexDigits.indexOf(source[pos++])
|
|
if (j < 0) throw FormatException("invalid hex digit in ${source} at ${pos - 1}")
|
|
result.add(((i shl 4) or j).toByte())
|
|
while (pos < source.length && (source[pos].isWhitespace())) pos++
|
|
}
|
|
return result.toByteArray()
|
|
}
|
|
|
|
fun ByteArray.flipSelf() {
|
|
var i = 0
|
|
var j = size - 1
|
|
while (i < j) {
|
|
val x = this[i]
|
|
this[i++] = this[j]
|
|
this[j--] = x
|
|
}
|
|
}
|
|
|
|
fun ByteArray.flip(): ByteArray = copyOf().also { it.flipSelf() }
|