Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memset to UnsafeMutablePointer<UInt8> in swift

I have a challenge with a variable with type UnsafeMutablePointer<UInt8>.

I have this working code to alloc and set to zero all an UInt8 array in Swift.
var bits = UnsafeMutablePointer<UInt8>(calloc(width * height, 8))

The problem is I'd like to do it without use the calloc method. I have this code to alloc the array
var bits = UnsafeMutablePointer<UInt8>.alloc(width * height)

but I can't find a method to set to zero all the memory.

I know I can do this, but I don't think is the best way.

for index in 0..< (width * height) {
    bits[index] = 0
}
like image 367
CrApHeR Avatar asked May 04 '15 02:05

CrApHeR


2 Answers

As @matt suggests, you can use initializeFrom to initialize the memory. I would use the Repeat collection type for this, as it avoids any interim allocation:

var bits = UnsafeMutablePointer<UInt8>.alloc(width * height)
bits.initializeFrom(Repeat(count: width * height, repeatedValue: 0))

(note, there’s no need to give the type of the value to Repeat, it can be inferred from the type of bits)

If you find you do this a lot, it might be worth creating a calloc-like extension to UnsafeMutablePointer:

extension UnsafeMutablePointer {
    // version that takes any kind of type for initial value
    static func calloc(num: Int, initialValue: T) -> UnsafeMutablePointer<T> {
        let ptr = UnsafeMutablePointer<T>.alloc(num)
        ptr.initializeFrom(Repeat(count: num, repeatedValue: initialValue))
        return ptr
    }

    // convenience version for integer-literal-creatable types 
    // that initializes to zero of that type
    static func calloc<I: IntegerLiteralConvertible>
      (num: Int) -> UnsafeMutablePointer<I> {
        return UnsafeMutablePointer<I>.calloc(num, initialValue: 0)
    }
}

// creates 100 UInt8s initialized to 0
var bits = UnsafeMutablePointer<UInt8>.calloc(100)
like image 88
Airspeed Velocity Avatar answered Oct 01 '22 00:10

Airspeed Velocity


You could say:

bits.initializeFrom(Array<UInt8>(count: width * height, repeatedValue: 0))

I'm guessing there's some underlying efficiency to copying the memory this way. But of course there's an inefficiency in that we temporarily make the array. [NOTE: AirspeedVelocity's answer shows a way to avoid that.]

Personally, I liked your original loop best, especially if you write it more compactly, like this:

(0 ..< (width*height)).map {bits[$0] = 0}
like image 26
matt Avatar answered Sep 30 '22 22:09

matt