Do you need help on a specific subject? Use the contact form (Request a blog entry) on the right hand side.

2015-07-03

Swift extensions: Bit access for UInt8

Sometimes it is necessary to address the individual bits in a byte. This extension adds that capability to the UInt8 type:

extension UInt8 {
    
    static var bit7mask: UInt8 { return 0b1000_0000 }
    static var bit6mask: UInt8 { return 0b0100_0000 }
    static var bit5mask: UInt8 { return 0b0010_0000 }
    static var bit4mask: UInt8 { return 0b0001_0000 }
    static var bit3mask: UInt8 { return 0b0000_1000 }
    static var bit2mask: UInt8 { return 0b0000_0100 }
    static var bit1mask: UInt8 { return 0b0000_0010 }
    static var bit0mask: UInt8 { return 0b0000_0001 }
    
    func toBools() -> (bit7: Bool, bit6: Bool, bit5: Bool, bit4: Bool, bit3: Bool, bit2: Bool, bit1: Bool, bit0: Bool) {
        return (
            self & UInt8.bit7mask == UInt8.bit7mask,
            self & UInt8.bit6mask == UInt8.bit6mask,
            self & UInt8.bit5mask == UInt8.bit5mask,
            self & UInt8.bit4mask == UInt8.bit4mask,
            self & UInt8.bit3mask == UInt8.bit3mask,
            self & UInt8.bit2mask == UInt8.bit2mask,
            self & UInt8.bit1mask == UInt8.bit1mask,
            self & UInt8.bit0mask == UInt8.bit0mask
        )
    }
        
    func bit7IsSet() -> Bool { return self & UInt8.bit7mask == UInt8.bit7mask }
    func bit6IsSet() -> Bool { return self & UInt8.bit6mask == UInt8.bit6mask }
    func bit5IsSet() -> Bool { return self & UInt8.bit5mask == UInt8.bit5mask }
    func bit4IsSet() -> Bool { return self & UInt8.bit4mask == UInt8.bit4mask }
    func bit3IsSet() -> Bool { return self & UInt8.bit3mask == UInt8.bit3mask }
    func bit2IsSet() -> Bool { return self & UInt8.bit2mask == UInt8.bit2mask }
    func bit1IsSet() -> Bool { return self & UInt8.bit1mask == UInt8.bit1mask }
    func bit0IsSet() -> Bool { return self & UInt8.bit0mask == UInt8.bit0mask }
    
    func bit7IsNotSet() -> Bool { return self & UInt8.bit7mask == 0 }
    func bit6IsNotSet() -> Bool { return self & UInt8.bit6mask == 0 }
    func bit5IsNotSet() -> Bool { return self & UInt8.bit5mask == 0 }
    func bit4IsNotSet() -> Bool { return self & UInt8.bit4mask == 0 }
    func bit3IsNotSet() -> Bool { return self & UInt8.bit3mask == 0 }
    func bit2IsNotSet() -> Bool { return self & UInt8.bit2mask == 0 }
    func bit1IsNotSet() -> Bool { return self & UInt8.bit1mask == 0 }
    func bit0IsNotSet() -> Bool { return self & UInt8.bit0mask == 0 }

}

The toBools() function is intended to be used as follows:

struct ID3v2_3_HeaderFlags {

    let unsynchronisation: Bool
    let extendedHeader: Bool
    let experimental: Bool
    
    
    /// Returns nil if the byte does not contain valid header flags
    
    init?(byte: UInt8) {
        
        let b4, b3, b2, b1, b0: Bool // Unused, should be zero
        (unsynchronisation, extendedHeader, experimental, b4, b3, b2, b1, b0) = byte.toBools()
        if b4 || b3 || b2 || b1 || b0 { return nil }
    }

}

What I like about this is that the tuple return guarantees us that the compiler will check if all bools have an assigned variable.

Happy coding...

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

No comments:

Post a Comment