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.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 { 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() 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() 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() }