Swift Converting Signed Array of Int [Int8] to Unsigned Array of Int [Uint8]

Swift converting signed array of Int [int8] to unsigned array of Int [UInt8]

If your intention is to convert signed 8-bit integers to
unsigned ones with the same bit representation (e.g. -1 -> 255):

let intArray: [Int8] =  [0, 1, 2, 127, -1, -2, -128]
let uintArray = intArray.map { UInt8(bitPattern: $0) }

print(uintArray)
// [0, 1, 2, 127, 255, 254, 128]

How to cast [Int8] to [UInt8] in Swift

I broadly agree with the other answers that you should just stick with map, however, if your array were truly huge, and it really was painful to create a whole second buffer just for converting to the same bit pattern, you could do it like this:

// first, change your process logic to be generic on any kind of container
func process<C: CollectionType where C.Generator.Element == UInt8>(chars: C) {
// just to prove it's working...
print(String(chars.map { UnicodeScalar($0) }))
}

// sample input
let a: [Int8] = [104, 101, 108, 108, 111] // ascii "Hello"

// access the underlying raw buffer as a pointer
a.withUnsafeBufferPointer { buf -> Void in
process(
UnsafeBufferPointer(
// cast the underlying pointer to the type you want
start: UnsafePointer(buf.baseAddress),
count: buf.count))
}
// this prints [h, e, l, l, o]

Note withUnsafeBufferPointer means what it says. It’s unsafe and you can corrupt memory if you get this wrong (be especially careful with the count). It works based on your external knowledge that, for example, if any of the integers are negative then your code doesn't mind them becoming corrupt unsigned integers. You might know that, but the Swift type system can't, so it won't allow it without resort to the unsafe types.

That said, the above code is correct and within the rules and these techniques are justifiable if you need the performance edge. You almost certainly won’t unless you’re dealing with gigantic amounts of data or writing a library that you will call a gazillion times.

It’s also worth noting that there are circumstances where an array is not actually backed by a contiguous buffer (for example if it were cast from an NSArray) in which case calling .withUnsafeBufferPointer will first copy all the elements into a contiguous array. Also, Swift arrays are growable so this copy of underlying elements happens often as the array grows. If performance is absolutely critical, you could consider allocating your own memory using UnsafeMutablePointer and using it fixed-size style using UnsafeBufferPointer.

For a humorous but definitely not within the rules example that you shouldn’t actually use, this will also work:

process(unsafeBitCast(a, [UInt8].self))

It's also worth noting that these solutions are not the same as a.map { UInt8($0) } since the latter will trap at runtime if you pass it a negative integer. If this is a possibility you may need to filter them first.

swift 3 ios : convert UInt8 Array to int8

You can convert a [UInt8] to a [Int8] by using this:

for el in uint8Array {
uint8Array.append(UInt8(bitPattern: el))
}

Swift 3.0 convert Data to ArrayUInt8

Got it!

var recived = [UInt8]()

func serialPort(_ serialPort: ORSSerialPort, didReceive data: Data) {
recived.removeAll()
print("recieved:\(data))")
recived.append(contentsOf: data)
}

Int8 array to signed hex string doesn't work when first byte is negative

I finally wrote my own solution, iterating the bytes and combining the string. Tested with different arrays, and works for both positive and negative hex.

extension Data {

func toSignedHexString() -> String {
// Create an empty string
var result = ""
var first: Int8 = 0

// Iterate bytes
var bytes = map { byte in
// Convert to Int8
return Int8(bitPattern: byte)
}
while !bytes.isEmpty {
// Get and remove the first byte
let byte = bytes.removeFirst()

// Check if this byte is the first byte
if result.isEmpty && first == 0 {
// Save the first byte
first = byte
} else if result.isEmpty && first != 0 {
// Convert two first bytes to hex
result.append(String(Int32(first + 1) * 256 + Int32(byte) + (first < 0 ? 1 : 0), radix: 16, uppercase: false))
} else {
// Convert it to hex
result.append(String(format: "%02hhx", first < 0 ? (Int32(bytes.isEmpty ? 256 : 255) - Int32(byte)) % 256 : byte))
}
}

// Return the final result
return result
}

}

Test code:

let bytes = Data([-100, -21, -46, 47, -99, 39, 67, 53, 62, -2, -23, 104, -15, 117, -9, 40, -31, 70, 4, 28].map({ UInt8(bitPattern: $0) }))
print(bytes.toSignedHexString() == "-63142dd062d8bccac10116970e8a08d71eb9fbe4")
// true

let bytes2 = Data([112, -84, -89, 120, -123, 118, -50, -7, -115, -97, -127, 41, -71, 52, -4, 105, -5, -80, 115, 86].map({ UInt8(bitPattern: $0) }))
print(bytes2.toSignedHexString() == "70aca7788576cef98d9f8129b934fc69fbb07356")
// true

What is the equivalent of this swift Uint8 conversion in c#?

Presumably instead of:

int txPower = frameBytes[1];

(which just extends an unsigned byte to 32 bits)

int txPower = (int)((sbyte)frameBytes[1]);

(which reinterpets the unsigned byte as a signed byte, then extends to 32 bits)

Note that the (int) can be done implicitly, if it is clearer:

int txPower = (sbyte)frameBytes[1];


Related Topics



Leave a reply



Submit