Created
August 21, 2016 22:24
-
-
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
This file contains 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
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