Skip to content

Instantly share code, notes, and snippets.

@codelynx
Last active November 29, 2016 19:39
Show Gist options
  • Select an option

  • Save codelynx/bc9f1e6129664e96b8c4de43913bc777 to your computer and use it in GitHub Desktop.

Select an option

Save codelynx/bc9f1e6129664e96b8c4de43913bc777 to your computer and use it in GitHub Desktop.
//
// ZWeakSet.swift
// ZKit
//
// The MIT License (MIT)
//
// Copyright (c) 2016 Electricwoods LLC, Kaz Yoshikawa.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import Foundation
private class ZWeakObject<T: AnyObject>: Hashable {
weak var object: T?
init(_ object: T) {
self.object = object
}
var hashValue: Int {
var hashValue = 0
if var object = object {
withUnsafePointer(to: &object, {
hashValue = $0.hashValue
})
}
return hashValue
}
}
private func == <T> (lhs: ZWeakObject<T>, rhs: ZWeakObject<T>) -> Bool {
return lhs.object === rhs.object
}
public class ZWeakSet<T: AnyObject>: Sequence {
private var _objects: Set<ZWeakObject<T>>
public init() {
_objects = Set<ZWeakObject<T>>()
}
public init(_ objects: [T]) {
self._objects = Set<ZWeakObject<T>>(objects.map { ZWeakObject($0) })
}
public var objects: [T] {
return _objects.flatMap { $0.object }
}
public func contains(object: T) -> Bool {
return self._objects.contains(ZWeakObject(object))
}
public func add(_ object: T) {
_objects.insert(ZWeakObject(object))
}
public func add(_ objects: [T]) {
_objects.formUnion(objects.map { ZWeakObject($0) })
}
public func remove(_ object: T) {
let items = _objects.filter { $0.object == nil || $0.object === object }
_objects = _objects.subtracting(items)
}
public func remove(_ objects: [T]) {
let items = _objects.filter { (object) in object.object == nil || objects.contains(where: { $0 === object }) }
_objects = _objects.subtracting(items)
}
public func makeIterator() -> AnyIterator<T> {
let objects = self.objects
var index = 0
return AnyIterator {
defer { index += 1 }
return index < objects.count ? objects[index] : nil
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment