如何使用按位运算符将带有 NSData 字节的 Obj-C 方法转换为 Swift

How to convert an Obj-C method with NSData bytes using bitwise operators to Swift

我正在尝试将 Objective C 方法转换为 Swift,但为了做到这一点,我需要一些帮助来了解发生了什么。

对于上下文,此方法的输入以 NSString 开始,然后转换为具有 utf8 编码的 NSData 对象。然后将此数据对象的字节传递给方法(message 参数)。

此方法的 return 值然后通过 writeData 发送到 CBPeripheral 的某个特征。

这是我的理解(从 Swift 的角度)。

我不是很了解按位运算符或者为什么下面的方法正在做它正在做的事情,因为没有文档。有人可以帮助清理其中的任何或所有部分吗?我希望编写此方法的 Swift 等效版本。谢谢。

- (uint32_t) computeCRC:(uint8_t *)message len:(NSUInteger)msgLen {

    uint32_t crcVal = 0, byteVal, mask;

    crcVal = 0xFFFFFFFF;
    for (int i=0; i<msgLen; i++) {
        byteVal = message[i];
        crcVal ^= byteVal;
        for (int j=7; j>=0; j--) {
            mask = -(crcVal&1);
            crcVal = (crcVal>>1)^(0xEDB88320 & mask);
        }
    }

    return ~crcVal;
}

与其从头开始编写实现,不如使用 crc32 的 zlib 实现?:

import zlib

func crc32(from data: Data) -> UInt {
    return data.withUnsafeBytes { (buffer: UnsafePointer<Bytef>) -> UInt in
       return zlib.crc32(0, buffer, uInt(data.count))
    }
}

但是,为了帮助您理解位运算:

func computeCRC(message: [UInt8]) -> UInt32 {
    var crc: UInt32 = 0xFFFFFFFF

    for byte in message {
        crc ^= UInt32(byte)
        for _ in 0 ..< 8 {
            // negation using 2-complement: -x = ~x + 1
            // use &+ addition with overflow
            let mask = ~(crc & 1) &+ 1
            crc = (crc >> 1) ^ (0xEDB88320 & mask)
        }
    }

    return ~crc
}

请注意,我们不需要传递 Swift 中的字节数。这些实现具有不同的签名,return 类型略有不同,但它们都给出相同的结果。

计算CRC16可以使用

import Foundation

extension Data {

    enum CRCType {
        case MODBUS
        case ARC
    }

    static func crc16(_ data: [UInt8], type: CRCType) -> UInt16? {
        if data.isEmpty {
            return nil
        }
        let polynomial: UInt16 = 0xA001 // A001 is the bit reverse of 8005
        var accumulator: UInt16
        // set the accumulator initial value based on CRC type
        if type == .ARC {
            accumulator = 0
        } else {
            // default to MODBUS
            accumulator = 0xFFFF
        }
        // main computation loop
        for byte in data {
            var tempByte = UInt16(byte)
            for _ in 0 ..< 8 {
                let temp1 = accumulator & 0x0001
                accumulator = accumulator >> 1
                let temp2 = tempByte & 0x0001
                tempByte = tempByte >> 1
                if (temp1 ^ temp2) == 1 {
                    accumulator = accumulator ^ polynomial
                }
            }
        }
        return accumulator
    }
}

来源here