forked from swiftlang/swift-corelibs-foundation
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNSValue.swift
167 lines (142 loc) · 5.02 KB
/
NSValue.swift
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
open class NSValue : NSObject, NSCopying, NSSecureCoding, NSCoding {
private static var SideTable = [ObjectIdentifier : NSValue]()
private static var SideTableLock = NSLock()
internal override init() {
super.init()
// on Darwin [NSValue new] returns nil
}
// because we cannot support the class cluster pattern owing to a lack of
// factory initialization methods, we maintain a sidetable mapping instances
// of NSValue to NSConcreteValue
internal var _concreteValue: NSValue {
get {
return NSValue.SideTableLock.synchronized {
return NSValue.SideTable[ObjectIdentifier(self)]!
}
}
set {
NSValue.SideTableLock.synchronized {
NSValue.SideTable[ObjectIdentifier(self)] = newValue
}
}
}
deinit {
if type(of: self) == NSValue.self {
NSValue.SideTableLock.synchronized {
NSValue.SideTable[ObjectIdentifier(self)] = nil
}
}
}
open override var hash: Int {
get {
if type(of: self) == NSValue.self {
return _concreteValue.hash
} else {
return super.hash
}
}
}
open override func isEqual(_ value: Any?) -> Bool {
guard let object = value as? NSValue else { return false }
if self === object {
return true
} else {
// bypass _concreteValue accessor in order to avoid acquiring lock twice
let (lhs, rhs) = NSValue.SideTableLock.synchronized {
return (NSValue.SideTable[ObjectIdentifier(self)],
NSValue.SideTable[ObjectIdentifier(object)])
}
guard let left = lhs, let right = rhs else { return false }
return left.isEqual(right)
}
}
open override var description : String {
get {
if type(of: self) == NSValue.self {
return _concreteValue.description
} else {
return super.description
}
}
}
open func getValue(_ value: UnsafeMutableRawPointer) {
if type(of: self) == NSValue.self {
return _concreteValue.getValue(value)
} else {
NSRequiresConcreteImplementation()
}
}
open var objCType: UnsafePointer<Int8> {
if type(of: self) == NSValue.self {
return _concreteValue.objCType
} else {
NSRequiresConcreteImplementation()
}
}
private static func _isSpecialObjCType(_ type: UnsafePointer<Int8>) -> Bool {
return NSSpecialValue._typeFromObjCType(type) != nil
}
public convenience required init(bytes value: UnsafeRawPointer, objCType type: UnsafePointer<Int8>) {
if Swift.type(of: self) == NSValue.self {
self.init()
if NSValue._isSpecialObjCType(type) {
self._concreteValue = NSSpecialValue(bytes: value.assumingMemoryBound(to: UInt8.self), objCType: type)
} else {
self._concreteValue = NSConcreteValue(bytes: value.assumingMemoryBound(to: UInt8.self), objCType: type)
}
} else {
NSRequiresConcreteImplementation()
}
}
public convenience required init?(coder aDecoder: NSCoder) {
if type(of: self) == NSValue.self {
self.init()
var concreteValue : NSValue? = nil
if aDecoder.containsValue(forKey: "NS.special") {
// It's unfortunate that we can't specialise types at runtime
concreteValue = NSSpecialValue(coder: aDecoder)
} else {
concreteValue = NSConcreteValue(coder: aDecoder)
}
guard concreteValue != nil else {
return nil
}
self._concreteValue = concreteValue!
} else {
NSRequiresConcreteImplementation()
}
}
open func encode(with aCoder: NSCoder) {
if type(of: self) == NSValue.self {
_concreteValue.encode(with: aCoder)
} else {
NSRequiresConcreteImplementation()
}
}
open class var supportsSecureCoding: Bool {
return true
}
open override func copy() -> Any {
return copy(with: nil)
}
open func copy(with zone: NSZone? = nil) -> Any {
return self
}
}
extension NSValue : _Factory {}
internal protocol _Factory {
init(factory: () -> Self)
}
extension _Factory {
init(factory: () -> Self) {
self = factory()
}
}