简体   繁体   English

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

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

I'm trying to convert an Objective C method to Swift but in order to do so I need some help understanding what's going on. 我正在尝试将Objective C方法转换为Swift,但为此,我需要一些帮助来了解发生了什么。

For context, the input to this method begins as an NSString which is then converted into an NSData object with utf8 encoding. 对于上下文,此方法的输入从NSString开始,然后将其转换为使用utf8编码的NSData对象。 The bytes of this data object are then passed into the method (the message parameter). 然后将此数据对象的字节传递到方法( message参数)中。

The return value of this method is then sent via writeData to a certain characteristic of a CBPeripheral . 然后,该方法的返回值通过writeData发送到CBPeripheral的某个特征。

Here's what I understand (from a Swift perspective). 这是我的理解(从Swift的角度来看)。

  • The message passed in is a UInt8 byte array: [UInt8] 传入的消息是一个UInt8字节数组: [UInt8]
  • 3 variables are created as UInt32 values; 创建3个变量作为UInt32值; crcVal , byteVal and mask crcValbyteValmask
  • crcVal is then set to the max value of UInt32 type 然后将crcVal设置为UInt32类型的最大值
  • each byte from the UInt8 byte array passed in is then looped through and some kind of operation is performed to produce and append to the final outcome of the crcVal value which is ultimately used to send via CoreBluetooth's writeData command to a CBPeripheral . 然后,将循环传入的UInt8字节数组中的每个字节,并执行某种操作以生成crcVal值的最终结果,该结果最终用于通过CoreBluetooth的writeData命令发送给CBPeripheral

I'm not very solid on bitwise operators or why the below method is doing what it's doing as there's no documentation. 我不太了解按位运算符,也不是因为没有文档,为什么下面的方法正在做它正在做的事情。 Can somebody help clear up any or all parts of this? 有人可以帮忙解决所有问题吗? I'm hoping to write a Swift equivalent version of this method. 我希望编写此方法的Swift等效版本。 Thank you. 谢谢。

- (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;
}

Instead of writing the implementation from scratch, why don't you use the zlib implementation of crc32 ?: 而不是从头开始编写实现,为什么不使用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))
    }
}

However, to help you understand the bitwise operations: 但是,为了帮助您了解按位操作:

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
}

Note that we don't need to pass the number of bytes in Swift. 注意,我们不需要在Swift中传递字节数。 The implementations have different signatures and return a slightly different type but they both give the same result. 这些实现具有不同的签名,并返回略有不同的类型,但是它们都给出相同的结果。

For calculation CRC16 you can use 对于计算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
    }
}

Source here 来源在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM