Last active
October 2, 2016 00:49
-
-
Save russbishop/96312bab409eb8a7c768ee2bc9d9a949 to your computer and use it in GitHub Desktop.
UnsafeArray
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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