| // 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 { |
| if let object = value as? NSValue { |
| 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)]) |
| } |
| if let lhs = lhs, let rhs = rhs { |
| return lhs.isEqual(rhs) |
| } |
| } |
| } |
| return false |
| } |
| |
| 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 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 |
| } |
| } |
| |