Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save wuftymerguftyguff/d41e2ca5609590c854b48e8a880e3c30 to your computer and use it in GitHub Desktop.
Save wuftymerguftyguff/d41e2ca5609590c854b48e8a880e3c30 to your computer and use it in GitHub Desktop.
Swift 3.0 String Extension to create NSData from a String representation of a hexadecimal value
extension String {
func replace(_ string:String, replacement:String) -> String {
return self.replacingOccurrences(of: string, with: replacement, options: NSString.CompareOptions.literal, range: nil)
}
func removeWhitespace() -> String {
return self.replace(" ", replacement: "")
}
/// Create NSData from hexadecimal string representation
///
/// This takes a hexadecimal representation and creates a NSData object. Note, if the string has any spaces, those are removed. Also if the string started with a '<' or ended with a '>', those are removed, too. This does no validation of the string to ensure it's a valid hexadecimal string
///
/// The use of `strtoul` inspired by Martin R at http://stackoverflow.com/a/26284562/1271826
///
/// - returns: NSData represented by this hexadecimal string. Returns nil if string contains characters outside the 0-9 and a-f range.
func dataFromHexadecimalString() -> NSData? {
//let trimmedString = self.stringByTrimmingCharactersInSet(NSCharacterSet(charactersInString: "<> ")).stringByReplacingOccurrencesOfString(" ", withString: "")
var trimmedString = self.replace("<", replacement: "")
trimmedString = self.replace(">", replacement: "")
trimmedString = self.removeWhitespace()
// make sure the cleaned up string consists solely of hex digits, and that we have even number of them
var error: NSError?
let regex: NSRegularExpression?
do {
regex = try NSRegularExpression(pattern: "^[0-9a-f]*$", options: .caseInsensitive)
} catch let error1 as NSError {
error = error1
regex = nil
}
let found = regex?.firstMatch(in: trimmedString, options: [], range: NSMakeRange(0, trimmedString.characters.count))
if found == nil || found?.range.location == NSNotFound || trimmedString.characters.count % 2 != 0 {
return nil
}
// everything ok, so now let's build NSData
let data = NSMutableData(capacity: trimmedString.characters.count / 2)
for i in stride(from:0,to:trimmedString.characters.count,by:2) {
let start = trimmedString.index(trimmedString.startIndex, offsetBy: i)
let end = trimmedString.index(trimmedString.startIndex, offsetBy: i+1)
// get a sub-string with a ClosedRange
let range = start...end
let byteString = trimmedString[range]
let num=UInt8(byteString.withCString { strtoul($0, nil, 16) })
print(byteString)
print(i)
data?.append([num] as [UInt8], length: 1)
}
return data
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment