I have this output from NSData: <00000100 84000c00 071490fe 4dfbd7e9>
So how could I byte reverse it in Swift and have this output: <00000001 0084000c 1407fe90 fb4de9d7>?
This should work to swap each pair of adjacent bytes in the data.
The idea is to interpret the bytes as an array of UInt16
integers
and use the built-in byteSwapped
property.
func swapUInt16Data(data : NSData) -> NSData {
// Copy data into UInt16 array:
let count = data.length / sizeof(UInt16)
var array = [UInt16](count: count, repeatedValue: 0)
data.getBytes(&array, length: count * sizeof(UInt16))
// Swap each integer:
for i in 0 ..< count {
array[i] = array[i].byteSwapped // *** (see below)
}
// Create NSData from array:
return NSData(bytes: &array, length: count * sizeof(UInt16))
}
If your actual intention is to convert data from an (external)
big-endian representation to the host (native) byte order (which happens to be little-endian on all current iOS and OS X devices) then you should replace ***
by
array[i] = UInt16(bigEndian: array[i])
Example:
var bytes : [UInt8] = [1, 2, 3, 4, 5, 6, 7, 8]
let data = NSData(bytes: &bytes, length: bytes.count)
print(data)
// <01020304 05060708>
print(swapUInt16Data(data))
// <02010403 06050807>
Update for Swift 3: The generic withUnsafeMutableBytes()
methods allows to obtain a UnsafeMutablePointer<UInt16>
to the bytes
and modify them directly:
func swapUInt16Data(data : Data) -> Data {
var mdata = data // make a mutable copy
let count = data.count / MemoryLayout<UInt16>.size
mdata.withUnsafeMutableBytes { (i16ptr: UnsafeMutablePointer<UInt16>) in
for i in 0..<count {
i16ptr[i] = i16ptr[i].byteSwapped
}
}
return mdata
}
Example:
let data = Data(bytes: [1, 2, 3, 4, 5, 6, 7, 8])
print(data as NSData) // <01020304 05060708>
let swapped = swapUInt16Data(data: data)
print(swapped as NSData) // <02010403 06050807>
CoreFoundation has CFSwapInt32BigToHost
and CFSwapInt32LittleToHost
and other swap functions.
In swift3 it looks like this
struct FileHeader {
var magicNumber: UInt32 = 0
var count: UInt32 = 0
var width: UInt32 = 0
var height: UInt32 = 0
static func create(data: Data) -> FileHeader {
let structSize = MemoryLayout<FileHeader>.size
assert(data.count >= structSize)
var result = FileHeader()
let nsdata = data as NSData
nsdata.getBytes(&result, range: NSRange(location: 0, length: structSize))
result.magicNumber = CFSwapInt32BigToHost(result.magicNumber)
result.count = CFSwapInt32BigToHost(result.count)
result.width = CFSwapInt32BigToHost(result.width)
result.height = CFSwapInt32BigToHost(result.height)
return result
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With