Skip to content

Instantly share code, notes, and snippets.

@drrost
Last active March 11, 2020 12:19
Show Gist options
  • Save drrost/ba328c4ef6ee0f7f6e10c3e8eb13526c to your computer and use it in GitHub Desktop.
Save drrost/ba328c4ef6ee0f7f6e10c3e8eb13526c to your computer and use it in GitHub Desktop.
Hexdump Data object to String
import Foundation
private let kHexHeader = "87654321 0011 2233 4455 6677 8899 aabb ccdd eeff 0123456789abcdef\n"
private let kLineHeader = "00000000:"
private let kLineLength = 16
extension Data {
func hexArray() -> String {
let array = [UInt8](self)
if array.isEmpty {
return "<data ojbect is empty>"
}
var result = "["
let count = array.count
for i in 0 ..< count {
result += NSString(format: "0x%02X", array[i]) as String
if i != count - 1 {
result += ", "
}
}
result += "]"
return result
}
func hex() -> String {
let array = [UInt8](self)
if array.isEmpty {
return "<data ojbect is empty>"
}
var result = kHexHeader
let count = array.count
if count != 0 {
for i in 0 ... (count - 1) / kLineLength {
let inRange = range(for: i, count: count)
let slice: [UInt8] = [UInt8](array[inRange])
result += line(for: slice, i)
}
}
return result
}
private func range(for i: Int, count: Int) -> ClosedRange<Int> {
let fristIndex = i * kLineLength
var length = kLineLength
if (count - i * kLineLength) < kLineLength {
length = count - i * kLineLength
}
let lastIndex = fristIndex + length - 1
return fristIndex...lastIndex
}
private func line(for bytes: [UInt8], _ index: Int) -> String {
var fullLine = lineHeader(for: index)
fullLine += hexLine(bytes)
fullLine += readableLine(bytes)
return fullLine + "\n"
}
private func lineHeader(for index: Int) -> String {
String(format:"%08X:", index)
}
private func hexLine(_ bytes: [UInt8]) -> String {
var result = ""
for (i, byte) in bytes.enumerated() {
if i % 2 == 0 {
result += " "
}
result += String(format:"%02X", byte)
}
let fullLineLength = 40
let spacesCount = fullLineLength - result.count + 2
return result + String(repeating: " ", count: spacesCount)
}
private func readableLine(_ bytes: [UInt8]) -> String {
var result = bytes.reduce("", { $0 + ($1 > 31 && $1 < 127 ? String(format: "%c", $1) : ".") })
let fullLineLength = 16
let spacesCount = fullLineLength - result.count
result += String(repeating: " ", count: spacesCount)
return result
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment