Last active
June 23, 2016 16:33
-
-
Save romainmenke/dd574ca063ca26c109795515e98e820e to your computer and use it in GitHub Desktop.
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
import Foundation | |
private class Weak<T : AnyObject> { | |
private weak var pointer : T? | |
private init(pointer:T) { self.pointer = pointer } | |
} | |
prefix operator § {} | |
postfix operator § {} | |
private prefix func §<T : AnyObject>(rhs:T) -> Weak<T> { | |
return Weak(pointer: rhs) | |
} | |
private prefix func §<T>(rhs:Weak<T>) -> T? { | |
return rhs.pointer | |
} | |
private postfix func §<T>(rhs:Weak<T>) -> T? { | |
return rhs.pointer | |
} | |
private func +<T>(lhs:[Weak<T>], rhs:T) -> [Weak<T>] { | |
var copy = lhs | |
copy.append(§rhs) | |
return copy | |
} | |
private func +=<T>(inout lhs:[Weak<T>], rhs:T) { | |
lhs.append(§rhs) | |
} | |
public final class WeakCollection<Element : AnyObject> : CollectionType, MutableCollectionType, _DestructorSafeContainer { | |
/// Always zero, which is the index of the first element when non-empty. | |
public var startIndex: Int { return 0 } | |
/// A "past-the-end" element index; the successor of the last valid | |
/// subscript argument. | |
public var endIndex: Int { clean(); return pointers.count } | |
/// Access the `index`th element. Reading is O(1). Writing is | |
/// O(1) unless `self`'s storage is shared with another live array; O(`count`) if `self` does not wrap a bridged `NSArray`; otherwise the efficiency is unspecified.. | |
public subscript (index: Int) -> Element { | |
get { | |
clean() | |
return pointers[index].pointer! | |
} set(value) { | |
clean() | |
pointers[index] = §value | |
} | |
} | |
public subscript (subRange: Range<Int>) -> ArraySlice<Element> { | |
get { | |
clean() | |
return (pointers.map { $0.pointer! })[subRange] | |
} set(value) { | |
clean() | |
var newPointers = (pointers.map { $0.pointer! }) | |
newPointers[subRange] = value | |
self.pointers = newPointers.map { §$0 } | |
} | |
} | |
private var pointers : [Weak<Element>] = [] | |
public init() {} | |
private func clean() { | |
while let index = (self.pointers.indexOf{ $0.pointer == nil }) { | |
self.pointers.removeAtIndex(index) | |
} | |
} | |
} | |
extension WeakCollection : ArrayLiteralConvertible { | |
/// Create an instance containing `elements`. | |
public convenience init(arrayLiteral elements: Element...) { | |
self.init() | |
var pointers : [Weak<Element>] = [] | |
for element in elements { | |
pointers += element | |
} | |
self.pointers = pointers | |
} | |
} | |
extension WeakCollection { | |
/// Construct a Array of `count` elements, each initialized to | |
/// `repeatedValue`. | |
public convenience init(count: Int, repeatedValue: Element) { | |
self.init() | |
for _ in 0..<count { | |
pointers.append(§repeatedValue) | |
} | |
} | |
/// The number of elements the Array stores. | |
public var count: Int { clean(); return pointers.count } | |
/// The number of elements the `Array` can store without reallocation. | |
public var capacity: Int { clean(); return pointers.count } | |
/// Reserve enough space to store `minimumCapacity` elements. | |
/// | |
/// - Postcondition: `capacity >= minimumCapacity` and the array has | |
/// mutable contiguous storage. | |
/// | |
/// - Complexity: O(`self.count`). | |
public func reserveCapacity(minimumCapacity: Int) { clean(); pointers.reserveCapacity(minimumCapacity) } | |
/// Append `newElement` to the Array. | |
/// | |
/// - Complexity: Amortized O(1) unless `self`'s storage is shared with another live array; O(`count`) if `self` does not wrap a bridged `NSArray`; otherwise the efficiency is unspecified.. | |
public func append(newElement: Element) { clean(); pointers.append(§newElement) } | |
/// Append the elements of `newElements` to `self`. | |
/// | |
/// - Complexity: O(*length of result*). | |
public func appendContentsOf<S : SequenceType where S.Generator.Element == Element>(newElements: S) { | |
clean() | |
for element in newElements { | |
pointers.append(§element) | |
} | |
} | |
/// Append the elements of `newElements` to `self`. | |
/// | |
/// - Complexity: O(*length of result*). | |
public func appendContentsOf<C : CollectionType where C.Generator.Element == Element>(newElements: C) { | |
clean() | |
for element in newElements { | |
pointers.append(§element) | |
} | |
} | |
/// Remove an element from the end of the Array in O(1). | |
/// | |
/// - Requires: `count > 0`. | |
public func removeLast() -> Element { | |
clean() | |
return pointers.removeLast().pointer! | |
} | |
/// Insert `newElement` at index `i`. | |
/// | |
/// - Requires: `i <= count`. | |
/// | |
/// - Complexity: O(`self.count`). | |
public func insert(newElement: Element, atIndex i: Int) { | |
clean() | |
pointers.insert(§newElement, atIndex: i) | |
} | |
/// Remove and return the element at index `i`. | |
/// | |
/// Invalidates all indices with respect to `self`. | |
/// | |
/// - Complexity: O(`self.count`). | |
public func removeAtIndex(index: Int) -> Element { | |
clean() | |
return (§(pointers.removeAtIndex(index)))! | |
} | |
/// Remove all elements. | |
/// | |
/// - Postcondition: `capacity == 0` iff `keepCapacity` is `false`. | |
/// | |
/// - Complexity: O(`self.count`). | |
public func removeAll(keepCapacity keepCapacity: Bool = true) { | |
pointers.removeAll(keepCapacity: keepCapacity) | |
} | |
} | |
extension WeakCollection : CustomStringConvertible, CustomDebugStringConvertible { | |
/// A textual representation of `self`. | |
public var description: String { clean(); return (self.map{ $0 }).description } | |
/// A textual representation of `self`, suitable for debugging. | |
public var debugDescription: String { clean(); return (self.map{ $0 }).debugDescription } | |
} | |
extension WeakCollection { | |
/// If `!self.isEmpty`, remove the last element and return it, otherwise | |
/// return `nil`. | |
/// | |
/// - Complexity: O(`self.count`) if the array is bridged, | |
/// otherwise O(1). | |
public func popLast() -> Element? { | |
clean() | |
return pointers.popLast()?.pointer | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment