Ios swift中任意位数的读取方法

Ios swift中任意位数的读取方法,ios,swift,binary,swift2,bit-manipulation,Ios,Swift,Binary,Swift2,Bit Manipulation,我试图用swift做一些二进制文件解析,虽然我有一些工作,但我有一个情况,我有变量字段 我的所有解析都在默认情况下工作 我抓住 1-bit field 1-bit field 1-bit field 11-bits field 1-bit field (optional) 4-bit field (optional) 4-bit field 1-bit field 2-bit field (optional) 4-bit field 5-bit field 6-bit field (option

我试图用swift做一些二进制文件解析,虽然我有一些工作,但我有一个情况,我有变量字段

我的所有解析都在默认情况下工作

我抓住

1-bit field
1-bit field
1-bit field
11-bits field
1-bit field
(optional) 4-bit field
(optional) 4-bit field
1-bit field
2-bit field
(optional) 4-bit field
5-bit field
6-bit field
(optional) 6-bit field
(optional) 24-bit field
(junk data - up until byte buffer 0 - 7 bits as needed)
大多数数据只使用一组特定的选项,所以我已经开始编写类来处理这些数据。我的一般方法是创建指针结构,然后从中构造字节数组:

let rawData: NSMutableData = NSMutableData(data: input_nsdata)
var ptr: UnsafeMutablePointer<UInt8> = UnsafeMutablePointer<UInt8(rawData.mutableBytes)
bytes = UnsafeMutableBufferPointer<UInt8>(start: ptr, count: rawData.length - offset)
所以,我遇到的麻烦是可选字段,因为我的数据并不具体位于字节边界上,所以一切都变得复杂起来。在理想的情况下,我可能只是直接使用指针,并根据需要将其按字节推进,然而,我没有意识到将指针推进3位的方法——这就引出了我的问题

处理我的情况最好的方法是什么

我的一个想法是提出各种反映可选字段的结构,除了在swift中我不确定如何创建位对齐的压缩结构


我最好的方法是什么?澄清-初始的
1位
字段确定设置了哪些可选字段。

如果字段不在字节边界上,则必须保留 当前字节和字节内当前位位置的轨迹

这里有一个可能的解决方案,允许读取任意数字 从数据数组中提取位,并进行所有簿记。唯一的 限制是
nextBits()
的结果必须适合
UInt
(32或64位,取决于平台)


这里是另一个可能的实现,它稍微简单一点 也许更有效。它将字节收集到一个
UInt
,然后 然后在单个步骤中提取结果。 这里的限制是
numBits+7
必须小于或等于 到
UInt
中的位数(32或64)。(当然
UInt
可替换为
UInt64
,使其独立于平台。)

struct位读取器{
私有出租数据:[UInt8]
私有变量字节偏移量=0
private var currentValue:UInt=0//仍需消耗的位
private var currentBits=0//currentValue中的有效位数`
初始化(数据:[UInt8]){
self.data=数据
}
func remainingBits()->Int{
返回8*(data.count-字节偏移量)+当前位
}
变异函数nextBits(numBits:Int)->UInt{
前提条件(NUMBUINT)(剩余)
//更新剩余位:

currentValue=currentValue&UInt(1)除非您特别希望设计自己的实现,否则我只会使用。@SamR.:CfitVector可以方便地管理大量位,但——除非我忽略了什么——无法帮助检索存储在多个位中的数字,可能是跨字节边界的。检索一个字段分隔的所有位从这些数据中建立数字可能不是很有效。
let b1 = (bytes[3] & 0x01) << 5
let b2 = (bytes[4] & 0xF8) >> 3
  return Int(b1 | b2)
struct BitReader {

    private let data : [UInt8]
    private var byteOffset : Int
    private var bitOffset : Int

    init(data : [UInt8]) {
        self.data = data
        self.byteOffset = 0
        self.bitOffset = 0
    }

    func remainingBits() -> Int {
        return 8 * (data.count - byteOffset) - bitOffset
    }

    mutating func nextBits(numBits : Int) -> UInt {
        precondition(numBits <= remainingBits(), "attempt to read more bits than available")

        var bits = numBits     // remaining bits to read
        var result : UInt = 0  // result accumulator

        // Read remaining bits from current byte:
        if bitOffset > 0 {
            if bitOffset + bits < 8 {
                result = (UInt(data[byteOffset]) & UInt(0xFF >> bitOffset)) >> UInt(8 - bitOffset - bits)
                bitOffset += bits
                return result
            } else {
                result = UInt(data[byteOffset]) & UInt(0xFF >> bitOffset)
                bits = bits - (8 - bitOffset)
                bitOffset = 0
                byteOffset = byteOffset + 1
            }
        }

        // Read entire bytes:
        while bits >= 8 {
            result = (result << UInt(8)) + UInt(data[byteOffset])
            byteOffset = byteOffset + 1
            bits = bits - 8
        }

        // Read remaining bits:
        if bits > 0 {
            result = (result << UInt(bits)) + (UInt(data[byteOffset]) >> UInt(8 - bits))
            bitOffset = bits
        }

        return result
    }
}
let data : [UInt8] = ... your data ...
var bitReader = BitReader(data: data)

let b1 = bitReader.nextBits(1)
let b2 = bitReader.nextBits(1)
let b3 = bitReader.nextBits(1)
let b4 = bitReader.nextBits(11)
let b5 = bitReader.nextBits(1)
if b1 > 0 {
    let b6 = bitReader.nextBits(4)
    let b7 = bitReader.nextBits(4)
}
// ... and so on ...
struct BitReader {
    private let data : [UInt8]
    private var byteOffset = 0
    private var currentValue : UInt = 0 // Bits which still have to be consumed 
    private var currentBits = 0         // Number of valid bits in `currentValue`

    init(data : [UInt8]) {
        self.data = data
    }

    func remainingBits() -> Int {
        return 8 * (data.count - byteOffset) + currentBits
    }

    mutating func nextBits(numBits : Int) -> UInt {
        precondition(numBits <= remainingBits(), "attempt to read more bits than available")

        // Collect bytes until we have enough bits:
        while currentBits < numBits {
            currentValue = (currentValue << 8) + UInt(data[byteOffset])
            currentBits = currentBits + 8
            byteOffset = byteOffset + 1
        }

        // Extract result:
        let remaining = currentBits - numBits
        let result = currentValue >> UInt(remaining)

        // Update remaining bits:
        currentValue = currentValue & UInt(1 << remaining - 1)
        currentBits = remaining
        return result
    }

}