-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathNSOrderedSet.swift
More file actions
89 lines (77 loc) · 2.45 KB
/
NSOrderedSet.swift
File metadata and controls
89 lines (77 loc) · 2.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import Foundation
private class Canary {}
public struct OrderedSet<Element: Comparable>: SortedSet {
fileprivate var storage = NSMutableOrderedSet()
fileprivate var canary = Canary()
public init() {}
}
extension OrderedSet {
public func forEach(_ body: (Element) -> Void) {
storage.forEach { body($0 as! Element) }
}
}
extension OrderedSet {
fileprivate static func compare(_ a: Any, _ b: Any) -> ComparisonResult
{
let a = a as! Element, b = b as! Element
if a < b { return .orderedAscending }
if a > b { return .orderedDescending }
return .orderedSame
}
}
extension OrderedSet {
public func index(of element: Element) -> Int? {
let index = storage.index(
of: element,
inSortedRange: NSRange(0 ..< storage.count),
usingComparator: OrderedSet.compare)
return index == NSNotFound ? nil : index
}
}
extension OrderedSet {
public func contains(_ element: Element) -> Bool {
return index(of: element) != nil
}
}
extension OrderedSet {
public func contains2(_ element: Element) -> Bool {
return storage.contains(element) || index(of: element) != nil
}
}
extension OrderedSet: RandomAccessCollection {
public typealias Index = Int
public typealias Indices = CountableRange<Int>
public var startIndex: Int { return 0 }
public var endIndex: Int { return storage.count }
public subscript(i: Int) -> Element { return storage[i] as! Element }
}
extension OrderedSet {
fileprivate mutating func makeUnique() {
if !isKnownUniquelyReferenced(&canary) {
storage = storage.mutableCopy() as! NSMutableOrderedSet
canary = Canary()
}
}
}
extension OrderedSet {
fileprivate func index(for value: Element) -> Int {
return storage.index(
of: value,
inSortedRange: NSRange(0 ..< storage.count),
options: .insertionIndex,
usingComparator: OrderedSet.compare)
}
}
extension OrderedSet {
@discardableResult
public mutating func insert(_ newElement: Element) -> (inserted: Bool, memberAfterInsert: Element)
{
let index = self.index(for: newElement)
if index < storage.count, storage[index] as! Element == newElement {
return (false, storage[index] as! Element)
}
makeUnique()
storage.insert(newElement, at: index)
return (true, newElement)
}
}