0

So in Swift 3, I had this function to convert a String representing Hexa data to Data type:

extension String {

public func fromHexStringtoData() -> Data? {
    func convertToUInt8(u: UInt16) -> UInt8? {
        switch(u) {
        case 0x30 ... 0x39:
            return UInt8(u - 0x30)
        case 0x41 ... 0x46:
            return UInt8(u - 0x41 + 10)
        case 0x61 ... 0x66:
            return UInt8(u - 0x61 + 10)
        default:
            return nil
        }
    }

    let utf16 = self.utf16
    guard let data = NSMutableData(capacity: utf16.count/2) else { return nil }
    var i = utf16.startIndex
    while i != utf16.endIndex {
        guard let hi = convertToUInt8(u: utf16[i]) else { return nil }

        //Need to convert following line to Swift 4
        guard let lo = convertToUInt8(u: utf16[i.advanced(by: 1)]) else { return nil }

        var value = hi << 4 + lo
        data.append(&value, length: 1)

        //Need to convert following line to Swift 4
        i = i.advanced(by: 2)
    }
    return data as Data
}

}

How can I convert the advanced(by: n) in an optimal way?

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
Kalzem
  • 7,320
  • 6
  • 54
  • 79

2 Answers2

0

You have to use like this :

extension String {
    public func fromHexStringtoData() -> Data? {
        func convertToUInt8(u: UInt16) -> UInt8? {
            switch(u) {
            case 0x30 ... 0x39:
                return UInt8(u - 0x30)
            case 0x41 ... 0x46:
                return UInt8(u - 0x41 + 10)
            case 0x61 ... 0x66:
                return UInt8(u - 0x61 + 10)
            default:
                return nil
            }
        }

        let utf16 = self.utf16
        guard let data = NSMutableData(capacity: utf16.count/2) else { return nil }
        var i = utf16.startIndex
        while i != utf16.endIndex {
            guard let hi = convertToUInt8(u: utf16[i]) else { return nil }

            //changed to Swift 4
            guard let lo = convertToUInt8(u: utf16[utf16.index(i, offsetBy: 1)]) else { return nil }

            var value = hi << 4 + lo
            data.append(&value, length: 1)

            //changed to Swift 4
            i = utf16.index(i, offsetBy: 2)
        }
        return data as Data
    }
}
Vini App
  • 7,339
  • 2
  • 26
  • 43
  • No need to use `utf16.index(I, offset: 2)`. `i = index(i, offsetBy: 2)` would be enough. the same applies to `utf16[utf16.index(i, offsetBy: 1)` you can use `utf16[index(after: i)` – Leo Dabus Oct 26 '17 at 01:38
0

This is not a direct answer to your question, but your code scans the input string from start to end, one way. In such cases, you can re-write your code without using indices:

extension String {
    public func fromHexStringToData() -> Data? {
        func convertToUInt8(u: UInt16) -> UInt8? {
            //...
        }

        var utf16Iterator = utf16.makeIterator()
        var data = Data(capacity: utf16.count/2)
        while let hiChar = utf16Iterator.next() {
            guard
                let hi = convertToUInt8(u: hiChar),
                let loChar = utf16Iterator.next(),
                let lo = convertToUInt8(u: loChar)
                else { return nil }

            let value = hi << 4 + lo
            data.append(value)
        }
        return data
    }
}

Works both in Swift 3 and Swift 4.

OOPer
  • 47,149
  • 6
  • 107
  • 142