> On Aug 4, 2016, at 11:42 PM, KS Sreeram via swift-users 
> <swift-users@swift.org> wrote:
> 
> I’m trying to initialize a byte-array efficiently with minimal copying with 
> the following steps:
> 
> 1. Create an empty byte array.
> 2. Reserve sufficient capacity in the array.
> 3. Use mutable pointers into the array to fill in the data.
> 4. The actual size that was filled is known only after it is filled in.
> 5. I would like to set the size of the array to the actual size.
> 
> I couldn’t find any methods for doing the last step. Is there a way to do 
> this?

I don't believe this is possible with an Array; the only way to work with 
uninitialized memory is with an UnsafeMutablePointer.

The simplest solution is probably to load the data into an allocated chunk of 
memory with an UnsafeMutablePointer and then create an NSData object to keep 
track of its lifetime. The `init(bytesNoCopy:length:deallocator:)` initializer 
can be used to make sure it deallocates the memory correctly.

If you don't *need* to use mutable pointers to fill the array, however, a 
custom SequenceType might be a better option. For instance, you could write a 
type like this which returns the data a byte at a time:

        struct MyDataSource: SequenceType, GeneratorType {
                ...
                
                init(...) {
                        ...
                }
                
                var initialCapacity: Int {
                        ...guess at the capacity...
                }
                
                mutating func next() -> UInt8? {
                        ...determine and return the next byte, or nil if you've 
reached the end...
                }
        }

Then you can write something like this:

        var source = MyDataSource(...)
        var array: [UInt8] = []
        array.reserveCapacity(source.initialCapacity)
        array.appendContentsOf(source)

And, et voila, `array` is full of your bytes. From what I can tell, if the 
capacity is already there, the standard library effectively uses a loop as 
tight as any you could hope for:

    let base = buffer.firstElementAddress

    while (nextItem != nil) && count < capacity {
      (base + count).initialize(to: nextItem!)
      count += 1
      nextItem = stream.next()
    }
    buffer.count = count

So I suspect a custom SequenceType will perform much better than you would 
first guess.

Hope this helps,
-- 
Brent Royal-Gordon
Architechies

_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Reply via email to