Skip to content

Instantly share code, notes, and snippets.

@russbishop
Last active October 2, 2016 00:49
Show Gist options
  • Save russbishop/96312bab409eb8a7c768ee2bc9d9a949 to your computer and use it in GitHub Desktop.
Save russbishop/96312bab409eb8a7c768ee2bc9d9a949 to your computer and use it in GitHub Desktop.
UnsafeArray
// MIT license, no warranty.
// Now updated for Swift 3.0
// Warning: This is just example code. In production you would want
// unit tests and ASAN tests.
/**
A thin wrapper over an unsafe buffer.
- warning: For the rare case where performance profiling has proven native Swift `Array` to be a problem.
This class should be used sparingly!
*/
public class UnsafeArray<T> : Sequence {
private var _capacity: Int
private var _count: Int
private var _storage: UnsafeMutablePointer<T>
/// - parameter capacity: The initial capacity. If exceeded the array will allocate new
/// storage and move the values to the new storage.
public init(capacity: Int) {
_capacity = capacity > 0 ? capacity : 8
_storage = UnsafeMutablePointer<T>.allocate(capacity: capacity)
_count = 0
}
deinit {
_storage.deinitialize(count: count)
_storage.deallocate(capacity: _capacity)
}
public var count: Int {
get {
return _count
}
}
public func append(newValue: T) {
if _count == _capacity {
let newCapacity = _capacity * 2
let newStorage = UnsafeMutablePointer<T>.allocate(capacity: newCapacity)
//move ownership (and copy values) from old storage to new storage
newStorage.moveInitialize(from: _storage, count: _count)
//deallocate old buffer; no deinit because we already moved
_storage.deallocate(capacity: _capacity)
_capacity = newCapacity
_storage = newStorage
}
_storage[count] = newValue
_count += 1
}
public subscript(index: Int) -> T {
get {
precondition(index < count, "Index \(index) outside bounds of array (0..<\(_count)).")
return _storage[index]
}
set {
precondition(index < count, "Index \(index) outside bounds of array (0..<\(_count)). Did you mean to append?")
_storage[index] = newValue
}
}
public func makeIterator() -> AnyIterator<T> {
var position = 0
return AnyIterator { () -> T? in
guard position < self.count else { return nil }
let value = self._storage[position]
position += 1
return value
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment