Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How in swift to convert Int16 to two UInt8 Bytes

I have some binary data that encodes a two byte value as a signed integer.

bytes[1] = 255  // 0xFF
bytes[2] = 251  // 0xF1

Decoding

This is fairly easy - I can extract an Int16 value from these bytes with:

Int16(bytes[1]) << 8 | Int16(bytes[2])

Encoding

This is where I'm running into issues. Most of my data spec called for UInt and that is easy but I'm having trouble extracting the two bytes that make up an Int16

let nv : Int16 = -15
UInt8(nv >> 8) // fail
UInt8(nv)      // fail

Question

How would I extract the two bytes that make up an Int16 value

like image 358
Jeef Avatar asked Sep 28 '15 20:09

Jeef


People also ask

How to convert [uint8] to data in Swift 5?

Updated for Swift 5, two things to pay attention: As [UInt8]is stored in a contiguous region of memory, there's no need to convert it to Data, pointer can access all bytes directly. Int's byte order is little endian currently on all Apple platform, but this is not garanteed on other platforms. say we want [0, 0, 0, 0x0e]to convert to 14.

What is the difference between INT8 and Int16 in Swift?

It turns out that Swift thinks that it is positive! Now the only difference between Int8 and Int16 is that the former is made up of a single byte, and the latter is made up of two bytes. Since it is made up of 2 bytes, an Int16 contains the range -32768 to 32767.

How to convert string to INT in Swift?

A variable can be declared as String type by following the below syntax, Swift provides the function of integer initializers using which we can convert a string into an Int type. To handle non-numeric strings, we can use nil coalescing using which the integer initializer returns an optional integer.

How do I convert a byte array to Int16?

The ToInt16 method converts the bytes from index startIndex to startIndex + 1 to an Int16 value. The order of bytes in the array must reflect the endianness of the computer system's architecture; for more information, see the Remarks section of the BitConverter class topic.


2 Answers

You should work with unsigned integers:

let bytes: [UInt8] = [255, 251]
let uInt16Value = UInt16(bytes[0]) << 8 | UInt16(bytes[1])
let uInt8Value0 = uInt16Value >> 8
let uInt8Value1 = UInt8(uInt16Value & 0x00ff)

If you want to convert UInt16 to bit equivalent Int16 then you can do it with specific initializer:

let int16Value: Int16 = -15
let uInt16Value = UInt16(bitPattern: int16Value)

And vice versa:

let uInt16Value: UInt16 = 65000
let int16Value = Int16(bitPattern: uInt16Value)

In your case:

let nv: Int16 = -15
let uNv = UInt16(bitPattern: nv)

UInt8(uNv >> 8)
UInt8(uNv & 0x00ff)
like image 141
mixel Avatar answered Oct 08 '22 21:10

mixel


You could use init(truncatingBitPattern: Int16) initializer:

let nv: Int16 = -15
UInt8(truncatingBitPattern: nv >> 8) // -> 255
UInt8(truncatingBitPattern: nv) // -> 241
like image 7
rintaro Avatar answered Oct 08 '22 19:10

rintaro