1

i found this PHP function to encode and decode a string to numbers. https://stackoverflow.com/a/8087840/10081776

works like a charm. and i can use it only in php. but i need this function in swift4 too but i can't figured out how to do this.

I try the following code but i don't know how to complete.

func toNumbers() -> String{
        let str = "abcdefg"
        let numbers = String(format: "%03d", str)
        let output = numbers + ??
        return numbers
    }



func backToString() -> String{
    let numbers = "1234560000"
    let str = ?
    return str
}

thanks for a quick help and have a nice weekend.

xyzcodeeee
  • 161
  • 2
  • 13

1 Answers1

3

The referenced PHP function returns a string with 3 decimal digits for each UTF-8 code unit in the source string. In Swift that would be

func toNumbers(_ s: String) -> String {
    return s.utf8.map { String(format: "%03d", $0) }.joined()
}

The reverse conversion is a bit more complicated because Swift has no built-in function which corresponds to the PHP str_split(). We have to iterate over the indices in steps of 3, and convert each slice to a byte:

func backToString(_ n: String) -> String? {
    var utf8 = Data()
    var from = n.startIndex
    while from < n.endIndex {
        guard let to = n.index(from, offsetBy: 3, limitedBy: n.endIndex) else { return nil }
        guard let u = UInt8(n[from..<to]) else { return nil }
        utf8.append(u)
        from = to
    }
    return String(data: utf8, encoding: .utf8)
}

The function returns an optional because the conversion can fail.

Example usage:

let s = "Wörks wíth all ストリングズ"
let n = toNumbers(s)
print(n) // 087195182114107115032119195173116104032097108108032227130185227131136227131170227131179227130176227130186
if let s2 = backToString(n) {
    print(s2) // Wörks wíth all ストリングズ
}

And just for fun: a more compact version of the second function:

func backToString(_ n: String) -> String? {
    return String(bytes: sequence(state: n.startIndex, next: { (from: inout String.Index) -> UInt8?  in
        guard let to = n.index(from, offsetBy: 3, limitedBy: n.endIndex) else { return nil }
        defer { from = to }
        return UInt8(n[from..<to])
    }), encoding: .utf8)
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382