UnsafePointer使用swift 2.0到swift 3.0

时间:2016-12-26 07:38:32

标签: swift

这是我用md5的swift 3.0的代码,但是UnsafePointer有3个地方的错误,我该如何解决?

let shift : [UInt32] = [7, 12, 17, 22, 5, 9, 14, 20, 4, 11, 16, 23, 6, 10, 15, 21]
let table: [UInt32] = (0 ..< 64).map { UInt32(0x100000000 * abs(sin(Double($0 + 1)))) }
     func md5( message: [UInt8]) -> [UInt8] {
            var message = message
            var messageLenBits = UInt64(message.count) * 8
            message.append(0x80)
            while message.count % 64 != 56 {
                message.append(0)
            }

            var lengthBytes = [UInt8](repeating: 0, count: 8)
            UnsafeMutablePointer<UInt64>(lengthBytes).memory = messageLenBits.littleEndian

            message += lengthBytes

    var a : UInt32 = 0x67452301
    var b : UInt32 = 0xEFCDAB89
    var c : UInt32 = 0x98BADCFE
    var d : UInt32 = 0x10325476
    for chunkOffset in stride(from: 0, to: message.count, by: 64) {
        let chunk = UnsafePointer<UInt32>(UnsafePointer<UInt8>(message) + chunkOffset)
        let originalA = a
        let originalB = b
        let originalC = c
        let originalD = d
        for j in 0 ..< 64 {
            var f : UInt32 = 0
            var bufferIndex = j
            let round = j >> 4
            switch round {
            case 0:
                f = (b & c) | (~b & d)
            case 1:
                f = (b & d) | (c & ~d)
                bufferIndex = (bufferIndex*5 + 1) & 0x0F
            case 2:
                f = b ^ c ^ d
                bufferIndex = (bufferIndex*3 + 5) & 0x0F
            case 3:
                f = c ^ (b | ~d)
                bufferIndex = (bufferIndex * 7) & 0x0F
            default:
                assert(false)
            }
            let sa = shift[(round<<2)|(j&3)]
            let tmp = a &+ f &+ UInt32(littleEndian: chunk[bufferIndex]) &+ table[j]
            a = d
            d = c
            c = b
            b = b &+ (tmp << sa | tmp >> (32-sa))
        }
        a = a &+ originalA
        b = b &+ originalB
        c = c &+ originalC
        d = d &+ originalD
    }



         var result = [UInt8](repeating: 0, count: 16)


            for (i, n) in [a, b, c, d].enumerated() {

               let pointer = UnsafeMutablePointer<UInt32>.allocate(capacity: 1)
                result[i] = UInt8(n.littleEndian)

            }
            return result

    }

1 个答案:

答案 0 :(得分:0)

将整数变量的(little-endian)值复制到 一个字节数组,你可以使用UnsafeMutableRawBufferPointer方法 var lengthBytes = [UInt8](repeating: 0, count: 8) lengthBytes.withUnsafeMutableBytes { $0.storeBytes(of: messageLenBits.littleEndian, as: UInt64.self) }

a

同样的方法可以复制bcd的最终值, result进入UInt8数组。

UInt32指针重新解释为withMemoryRebound()指针已完成 与 (UnsafePointer(message) + chunkOffset).withMemoryRebound(to: UInt32.self, capacity: 16) { chunk in // ... let tmp = a &+ f &+ UInt32(littleEndian: chunk[bufferIndex]) &+ table[j] // ... }

func md5( message: [UInt8]) -> [UInt8] {
    var message = message
    let messageLenBits = UInt64(message.count) * 8
    message.append(0x80)
    while message.count % 64 != 56 {
        message.append(0)
    }

    var lengthBytes = [UInt8](repeating: 0, count: 8)
    lengthBytes.withUnsafeMutableBytes {
        $0.storeBytes(of: messageLenBits.littleEndian, as: UInt64.self)
    }
    message += lengthBytes

    var a : UInt32 = 0x67452301
    var b : UInt32 = 0xEFCDAB89
    var c : UInt32 = 0x98BADCFE
    var d : UInt32 = 0x10325476
    for chunkOffset in stride(from: 0, to: message.count, by: 64) {
        (UnsafePointer(message) + chunkOffset).withMemoryRebound(to: UInt32.self, capacity: 16) {
            chunk in

            let originalA = a
            let originalB = b
            let originalC = c
            let originalD = d
            for j in 0 ..< 64 {
                var f : UInt32 = 0
                var bufferIndex = j
                let round = j >> 4
                switch round {
                case 0:
                    f = (b & c) | (~b & d)
                case 1:
                    f = (b & d) | (c & ~d)
                    bufferIndex = (bufferIndex*5 + 1) & 0x0F
                case 2:
                    f = b ^ c ^ d
                    bufferIndex = (bufferIndex*3 + 5) & 0x0F
                case 3:
                    f = c ^ (b | ~d)
                    bufferIndex = (bufferIndex * 7) & 0x0F
                default:
                    assert(false)
                }
                let sa = shift[(round<<2)|(j&3)]
                let tmp = a &+ f &+ UInt32(littleEndian: chunk[bufferIndex]) &+ table[j]
                a = d
                d = c
                c = b
                b = b &+ (tmp << sa | tmp >> (32-sa))
            }
            a = a &+ originalA
            b = b &+ originalB
            c = c &+ originalC
            d = d &+ originalD
        }
    }
    var result = [UInt8](repeating: 0, count: 16)
    result.withUnsafeMutableBytes { ptr in
        ptr.storeBytes(of: a.littleEndian, toByteOffset: 0, as: UInt32.self)
        ptr.storeBytes(of: b.littleEndian, toByteOffset: 4, as: UInt32.self)
        ptr.storeBytes(of: c.littleEndian, toByteOffset: 8, as: UInt32.self)
        ptr.storeBytes(of: d.littleEndian, toByteOffset: 12, as: UInt32.self)
    }
    return result
}

总而言之,你的方法就变成了

$query = $this->createQuery();
$query->statement('
    SELECT * 
    FROM tx_myext_domain_model_item 
    WHERE uid NOT IN(
        SELECT foreign_uid FROM tx_myext_item_object_mm
    )
');
$query->execute();