Guest User

Untitled

a guest
May 25th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.46 KB | None | 0 0
  1. public struct PointerKeyedMap<Key, Value> where Key: AnyObject {
  2.  
  3. public typealias Element = (key: Key, value: Value)
  4.  
  5. public subscript(key: Key) -> Value? {
  6. get {
  7. guard capacity > 0 else { return nil }
  8. let i = bucketIndex(for: key)
  9. return buckets[i].first(where: { $0.key === key })?.value
  10. }
  11.  
  12. set {
  13. if newValue != nil {
  14. guard capacity > 0 else {
  15. self.buckets = [[(key: key, value: newValue!)]]
  16. return
  17. }
  18.  
  19. let i = bucketIndex(for: key)
  20. if let j = buckets[i].index(where: { $0.key === key }) {
  21. buckets[i][j] = (key: key, value: newValue!)
  22. } else {
  23. if Double(count) > 0.75 * Double(capacity) {
  24. reserveCapacity(n: capacity * 2)
  25. }
  26. buckets[i].append((key: key, value: newValue!))
  27. }
  28. } else {
  29. guard capacity > 0 else { return }
  30. let i = bucketIndex(for: key)
  31. if let j = buckets[i].index(where: { $0.key === key }) {
  32. buckets[i].remove(at: j)
  33. }
  34. }
  35. }
  36. }
  37.  
  38. public mutating func reserveCapacity(n: Int) {
  39. var newBuckets: [[Element]] = Array.init(repeating: [], count: n)
  40. for pair in self {
  41. let i = bucketIndex(for: pair.key, capacity: n)
  42. newBuckets[i].append(pair)
  43. }
  44. self.buckets = newBuckets
  45. }
  46.  
  47. public var count: Int {
  48. return buckets.reduce(0) { $0 + $1.count }
  49. }
  50.  
  51. public var capacity: Int {
  52. return buckets.count
  53. }
  54.  
  55. private func bucketIndex(for key: Key, capacity: Int? = nil) -> Int {
  56. var ref = key
  57. return withUnsafePointer(to: &ref) { Int(bitPattern: $0) } % (capacity ?? self.capacity)
  58. }
  59.  
  60. private var buckets: [[Element]]
  61.  
  62. }
  63.  
  64. extension PointerKeyedMap: Collection {
  65.  
  66. public typealias Index = PointerKeyedMapIndex
  67.  
  68. public subscript(i: Index) -> Element {
  69. return buckets[i.bucketIndex][i.cellIndex]
  70. }
  71.  
  72. public var startIndex: Index {
  73. if let i = buckets.index(where: { !$0.isEmpty }) {
  74. return Index(bucketIndex: i, cellIndex: 0)
  75. } else {
  76. return endIndex
  77. }
  78. }
  79.  
  80. public var endIndex: Index {
  81. return Index(bucketIndex: buckets.count, cellIndex: 0)
  82. }
  83.  
  84. public func index(after i: Index) -> Index {
  85. if i.cellIndex < (buckets[i.bucketIndex].count - 1) {
  86. return Index(bucketIndex: i.bucketIndex, cellIndex: i.cellIndex + 1)
  87. } else if let i = buckets.dropFirst(i.bucketIndex + 1).index(where: { !$0.isEmpty }) {
  88. return Index(bucketIndex: i, cellIndex: 0)
  89. } else {
  90. return endIndex
  91. }
  92. }
  93.  
  94. }
  95.  
  96. extension PointerKeyedMap: ExpressibleByDictionaryLiteral {
  97.  
  98. public init(dictionaryLiteral elements: (Key, Value)...) {
  99. self.buckets = Array(repeating: [], count: elements.count * 2)
  100. for (key, value) in elements {
  101. self[key] = value
  102. }
  103. }
  104.  
  105. }
  106.  
  107. public struct PointerKeyedMapIndex: Comparable {
  108.  
  109. fileprivate let bucketIndex: Int
  110. fileprivate let cellIndex: Int
  111.  
  112. public static func < (lhs: PointerKeyedMapIndex, rhs: PointerKeyedMapIndex) -> Bool {
  113. return lhs.bucketIndex == rhs.bucketIndex
  114. ? lhs.cellIndex < rhs.cellIndex
  115. : lhs.bucketIndex < rhs.bucketIndex
  116. }
  117.  
  118. }
Add Comment
Please, Sign In to add comment