How to Byte Reverse Nsdata Output in Swift The Littleendian Way

How to byte reverse NSData output in Swift the littleEndian way?

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>

Changing NSData byte order to little endian

    NSData *manufData = [NSData dataWithBytes:"12345AT18" length:9];
NSMutableData *pillowData = [[manufData subdataWithRange:NSMakeRange(5, 4)] mutableCopy];
uint32_t *bytes = pillowData.mutableBytes;
*bytes = CFSwapInt32(*bytes);
NSLog(@"%@", pillowData);

Output:

2018-01-25 15:52:39.067805-0600 test[23520:1338453] <38315441>

Note that this doesn't change the contents of manufData. It only changes the copy of the bytes in pillowData.

Converted NSData to Data in Swift, and now when I try to cast bytes to [UInt] I get a crash

The reason you are crashing is this expression:

bytes : UnsafePointer<[UInt]>

You are assuming that the data represents a series of UInt. So a pointer to the start of the data is not as unsafe pointer to a [UInt], an array of UInt; it is an unsafe pointer to a UInt, i.e. the first in the series. You should be saying:

bytes : UnsafePointer<UInt>

So much for the crash. Now let's talk about the thing you are mostly trying to do here.

I'm uncertain what the string format is supposed to do, but I do grasp that the idea of ntohl is to guarantee the endianity of some C long ints (32 bits). So I'll omit the string format part and just talk about how you would take a stream of C long int received into a Data and reverse the endianity of the long ints.

Suppose d is a mutable Data (i.e. declared with var). Then, assuming it represents a sequence of UInt32 little-endian values and you want to convert those to big-endian, you would say:

let ct = d.count/4
d.withUnsafeMutableBytes{
(ptr:UnsafeMutablePointer<UInt32>) in
for ix in 0..<ct {
ptr[ix] = ptr[ix].bigEndian
}
}

Sorting memory fixing Byte order Endian

Swapping bytes in an element is a common idiom: you go up to the half of the bytes and exchange with the symetric byte. You just have to iterate your buffer as bytes, element by element.

Code could be:

void fixEncoding(void* StoredData, uint8_t variableSizeInBytes, uint8_t buffer_size) {
char* data = StoredData; // must be char to be able to use pointer arithmetics
while (buffer_size > 0) {
int i;
// swap the element at data
for (i = 0; i < variableSizeInBytes / 2; i++) {
int j = variableSizeInBytes - i - 1;
char t = data[i];
data[i] = data[j];
data[j] = t;
}
// skip to next element
data += variableSizeInBytes;
buffer_size -= variableSizeInBytes;
}
}

How to convert an ContiguousArray of Floats into a byte array in Swift?

You can use the withUnsafeBytes() method to get a buffer pointer to the underlying bytes of the array's contiguous storage, and directly initialize an [UInt8] array from that buffer pointer. Example:

let floatArray: [Float] = [1.0, 2.0]
// Works also with a ContiguousArray:
// let floatArray: ContiguousArray<Float> = [1.0, 2.0]

let byteArray = floatArray.withUnsafeBytes { Array($0) }
print(byteArray) // [0, 0, 128, 63, 0, 0, 0, 64]

Equivalently (based on Leo's suggestion):

let byteArray = floatArray.withUnsafeBytes(Array.init)

The byte array contains the binary representation of the floating point numbers in host byte order (which is little-endian on all current Apple platforms). A conversion to big-endian is possible, but not without an intermediate copy to an integer array:

let floatArray: ContiguousArray<Float> = [1.0, 2.0]
let intArray = floatArray.map { $0.bitPattern.bigEndian }
let byteArray = intArray.withUnsafeBytes(Array.init)
print(byteArray) // 63, 128, 0, 0, 64, 0, 0, 0]

Reverse conversion: A simple method would be

let floatArray2 = byteArray.withUnsafeBytes { Array($0.bindMemory(to: Float.self)) }
print(floatArray2) // [1.0, 2.0]

However, that requires that the element storage of the byte array is properly aligned for floating point numbers. If that is not guaranteed then you can do

var floatArray2 = [Float](repeating: 0.0, count: byteArray.count / MemoryLayout<Float>.stride)
_ = floatArray2.withUnsafeMutableBytes { byteArray.copyBytes(to: $0) }
print(floatArray2) // [1.0, 2.0]

Convert a two byte UInt8 array to a UInt16 in Swift

If you want to go via NSData then it would work like this:

let bytes:[UInt8] = [0x01, 0x02]
println("bytes: \(bytes)") // bytes: [1, 2]
let data = NSData(bytes: bytes, length: 2)
print("data: \(data)") // data: <0102>

var u16 : UInt16 = 0 ; data.getBytes(&u16)
// Or:
let u16 = UnsafePointer<UInt16>(data.bytes).memory

println("u16: \(u16)") // u16: 513

Alternatively:

let bytes:[UInt8] = [0x01, 0x02]
let u16 = UnsafePointer<UInt16>(bytes).memory
print("u16: \(u16)") // u16: 513

Both variants assume that the bytes are in the host byte order.

Update for Swift 3 (Xcode 8):

let bytes: [UInt8] = [0x01, 0x02]
let u16 = UnsafePointer(bytes).withMemoryRebound(to: UInt16.self, capacity: 1) {
$0.pointee
}
print("u16: \(u16)") // u16: 513

Little endian bitmaps & Unable to create GMSGLImageTile due to bad graphics data

That error will occur if your PNG images for your tiles are not set to 8-bit color depth.

Changing the color depth of your images to 8-bits should fix the problem.

Swift: How to convert Bytes into a float / get a more precise number?

The problem is that you're trying to turn little endian UInt32 values into Float merely by "reinterpreting" the same bit patterns as a new value (that's what Float(bitPattern:) is for), but that's not at all how Float stores its data. Swift's Float and Double datatypes are implementations of the 32 and 64 bit floating point data types from IEEE 754. There's plenty of online resources that explain it, but the TL;DR is that they store numbers in a similar way as scientific notation, with a mantissa raised to the power of an exponent.

I think part of your difficulty comes from trying to do too much at once. Break it down into small pieces. Write a function that takes your data, and decomposes it into the 3 UInt32 components. Then write a separate function that does whatever transformation you want on those components, such as turning them into floats. Here's a rough example:

import Foundation

func createTestData(x: UInt32, y: UInt32, z: UInt32) -> Data {
return [x, y, z]
.map { UInt32(littleEndian: $0) }
.withUnsafeBufferPointer { Data(buffer: $0) }
}

func decode(data: Data) -> (x: UInt32, y: UInt32, z: UInt32) {
let values = data.withUnsafeBytes { bufferPointer in
bufferPointer
.bindMemory(to: UInt32.self)
.map { rawBitPattern in
return UInt32(littleEndian: rawBitPattern)
}
}

assert(values.count == 3)
return (x: values[0], y: values[1], z: values[2])
}

func transform(ints: (x: UInt32, y: UInt32, z: UInt32))
-> (x: Float, y: Float, z: Float) {
let transform: (UInt32) -> Float = { Float($0) / 1000 } // define whatever transformation you need
return (transform(ints.x), transform(ints.y), transform(ints.z))
}

let testData = createTestData(x: 123, y: 456, z: 789)
print(testData) // => 12 bytes
let decodedVector = decode(data: testData)
print(decodedVector) // => (x: 123, y: 456, z: 789)
let intsToFloats = transform(ints: decodedVector)
print(intsToFloats) // => (x: 0.123, y: 0.456, z: 0.789)

Are big endian and little endian values portable?

00000000 | 00000000 | 00000000 | 00001010 // big    endian

00001010 | 00000000 | 00000000 | 00000000 // little endian

Whether data is stored in big endian or little endian mode mostly only matters if you're trying to access a smaller portion of a variable in memory, usually via a pointer, like trying to access the least significant character of a 32 bit integer via a pointer to character or a union with a character array. Another example of an issue is if you read data from a file directly into an array of 32 bit integers or if you write data from an array of 32 bit integers. The data in the file will usually be also stored in little endian or big endian mode.

As far as I'm aware, there's no generic compile time method to determine if the cpu is running in big endian mode or little endian mode (specific compilers may have defines for this). You could write test code using a union of 32 bit integer and a character array of size 4. Then set the integer in the union to 10, and check to see if the union character array[0] contains the 10 which means little endian mode, or if the union character array[3] contains the 10, which means big endian mode. Other methods to determine if the CPU is in little endian or big endian mode are possible.

Once you determine if the cpu is in little endian or big endian mode, you can include conditional code to handle both cases, such as the file I/O to / from an array of 32 bit integers. If you wanted the file data to be in big endian mode, but your cpu is in little endian mode, you'd have to reverse the bytes of each integer before writing or after reading from a file.

You could also write code sequences to store data in big endian mode, regardless of the cpu mode. It would waste time if already in big endian mode, but it works for both big and little endian mode:

char     buffer[256];
char * ptr2char;
uint32_t uint32bit;
/* ... */
ptr2char = buffer; /* store uint32bit in big endian mode */
*ptr2char++ = (uint32bit >> 24)&0xff;
*ptr2char++ = (uint32bit >> 16)&0xff;
*ptr2char++ = (uint32bit >> 8)&0xff;
*ptr2char++ = (uint32bit )&0xff;


Related Topics



Leave a reply



Submit