swiftpointersunsafe-pointersunsafemutablepointer

How to copy memory to an UnsafeMutableRawPointer starting from an index in Swift?


I know how to copy memory from an array to an UnsafeMutableRawPointer starting at index 0 by using:

mutableRawPointer.copyMemory(from: bytes, byteCount: bytes.count * MemoryLayout<Float>.stride)

where bytes is an array of floats.

However, I would like to copy from my array to a mutable raw pointer starting from an index that might not be zero.

Eg.:

let array: [Float] = [1, 2, 3]

copyMemoryStartingAtIndex(to: myPointer, from: array, startIndexAtPointer: 2)

So, if the pointee was [0, 0, 0, 0, 0], it will become [0, 0, 1, 2, 3].

How can I achieve this in Swift 4?


Solution

  • You can write something like this:

    //Caution: when T is not a `primitive` type, this code may cause severe memory issue
    func copyMemoryStartingAtIndex<T>(to umrp: UnsafeMutableRawPointer, from arr: [T], startIndexAtPointer toIndex: Int) {
        let byteOffset = MemoryLayout<T>.stride * toIndex
        let byteCount = MemoryLayout<T>.stride * arr.count
        umrp.advanced(by: byteOffset).copyMemory(from: arr, byteCount: byteCount)
    }
    

    Testing code:

    let size = MemoryLayout<Float>.stride * 5
    let myPointer = UnsafeMutableRawPointer.allocate(byteCount: size, alignment: MemoryLayout<Float>.alignment)
    defer {myPointer.deallocate()}
    
    let uint8ptr = myPointer.initializeMemory(as: UInt8.self, repeating: 0, count: size)
    defer {uint8ptr.deinitialize(count: size)}
    
    func dump(_ urp: UnsafeRawPointer, _ size: Int) {
        let urbp = UnsafeRawBufferPointer(start: urp, count: size)
        print(urbp.map{String(format: "%02X", $0)}.joined(separator: " "))
    }
    
    let array: [Float] = [1, 2, 3]
    
    dump(myPointer, size)
    copyMemoryStartingAtIndex(to: myPointer, from: array, startIndexAtPointer: 2)
    dump(myPointer, size)
    

    Output:

    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    00 00 00 00 00 00 00 00 00 00 80 3F 00 00 00 40 00 00 40 40
    

    But, I recommend you to consider what Hamish says in the comment.