Using regular expression matching is one possible method to extract the
"hex numbers" from the string.
What you are looking for is an optional "0x", followed by exactly
2 hex digits. The corresponding regex pattern is "(0x)?([0-9a-f]{2})"
.
Then you can convert each match to a Character
and finally concatenate
the characters to a String
, quite similar to your "partial implementation". Instead of strtoul()
you can use the UInt32
initializer
init?(_ text: String, radix: Int = default)
which is new in Swift 2.
The pattern has two "capture groups" (encloses in parentheses),
the first one matches the optional "0x", and the second one matches
the two hex digits, the corresponding range can be retrieved with
rangeAtIndex(2)
.
This leads to the following implementation which can handle all
your sample strings:
func hexStringtoAscii(hexString : String) -> String {
let pattern = "(0x)?([0-9a-f]{2})"
let regex = try! NSRegularExpression(pattern: pattern, options: .CaseInsensitive)
let nsString = hexString as NSString
let matches = regex.matchesInString(hexString, options: [], range: NSMakeRange(0, nsString.length))
let characters = matches.map {
Character(UnicodeScalar(UInt32(nsString.substringWithRange($0.rangeAtIndex(2)), radix: 16)!))
}
return String(characters)
}
(See Swift extract regex matches for an explanation for the conversion to NSString
.)
Note that this function is quite lenient, it just searches for
2-digit hex strings and ignores all other characters, so this
would be accepted as well:
let str6 = "4d+-4c*/4e0x63"
Update for Swift 5.1:
func hexStringtoAscii(_ hexString : String) -> String {
let pattern = "(0x)?([0-9a-f]{2})"
let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)
let nsString = hexString as NSString
let matches = regex.matches(in: hexString, options: [], range: NSMakeRange(0, nsString.length))
let characters = matches.map {
Character(UnicodeScalar(UInt32(nsString.substring(with: $0.range(at: 2)), radix: 16)!)!)
}
return String(characters)
}