blob: 7dc8cc808c4dfb4b76f4fe7c7aed3ec63bc2838c [file] [log] [blame]
// 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
//
import CoreFoundation
#if os(OSX) || os(iOS)
internal let kCFNumberSInt8Type = CFNumberType.sInt8Type
internal let kCFNumberSInt16Type = CFNumberType.sInt16Type
internal let kCFNumberSInt32Type = CFNumberType.sInt32Type
internal let kCFNumberSInt64Type = CFNumberType.sInt64Type
internal let kCFNumberFloat32Type = CFNumberType.float32Type
internal let kCFNumberFloat64Type = CFNumberType.float64Type
internal let kCFNumberCharType = CFNumberType.charType
internal let kCFNumberShortType = CFNumberType.shortType
internal let kCFNumberIntType = CFNumberType.intType
internal let kCFNumberLongType = CFNumberType.longType
internal let kCFNumberLongLongType = CFNumberType.longLongType
internal let kCFNumberFloatType = CFNumberType.floatType
internal let kCFNumberDoubleType = CFNumberType.doubleType
internal let kCFNumberCFIndexType = CFNumberType.cfIndexType
internal let kCFNumberNSIntegerType = CFNumberType.nsIntegerType
internal let kCFNumberCGFloatType = CFNumberType.cgFloatType
internal let kCFNumberSInt128Type = CFNumberType(rawValue: 17)!
#else
internal let kCFNumberSInt128Type: CFNumberType = 17
#endif
extension Int8 : _ObjectTypeBridgeable {
@available(swift, deprecated: 4, renamed: "init(truncating:)")
public init(_ number: NSNumber) {
self = number.int8Value
}
public init(truncating number: NSNumber) {
self = number.int8Value
}
public init?(exactly number: NSNumber) {
let value = number.int8Value
guard NSNumber(value: value) == number else { return nil }
self = value
}
public func _bridgeToObjectiveC() -> NSNumber {
return NSNumber(value: self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Int8?) {
result = _unconditionallyBridgeFromObjectiveC(x)
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Int8?) -> Bool {
guard let value = Int8(exactly: x) else { return false }
result = value
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Int8 {
var result: Int8?
guard let src = source else { return Int8(0) }
guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Int8(0) }
return result!
}
}
extension UInt8 : _ObjectTypeBridgeable {
@available(swift, deprecated: 4, renamed: "init(truncating:)")
public init(_ number: NSNumber) {
self = number.uint8Value
}
public init(truncating number: NSNumber) {
self = number.uint8Value
}
public init?(exactly number: NSNumber) {
let value = number.uint8Value
guard NSNumber(value: value) == number else { return nil }
self = value
}
public func _bridgeToObjectiveC() -> NSNumber {
return NSNumber(value: self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt8?) {
result = _unconditionallyBridgeFromObjectiveC(x)
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt8?) -> Bool {
guard let value = UInt8(exactly: x) else { return false }
result = value
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> UInt8 {
var result: UInt8?
guard let src = source else { return UInt8(0) }
guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return UInt8(0) }
return result!
}
}
extension Int16 : _ObjectTypeBridgeable {
@available(swift, deprecated: 4, renamed: "init(truncating:)")
public init(_ number: NSNumber) {
self = number.int16Value
}
public init(truncating number: NSNumber) {
self = number.int16Value
}
public init?(exactly number: NSNumber) {
let value = number.int16Value
guard NSNumber(value: value) == number else { return nil }
self = value
}
public func _bridgeToObjectiveC() -> NSNumber {
return NSNumber(value: self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Int16?) {
result = _unconditionallyBridgeFromObjectiveC(x)
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Int16?) -> Bool {
guard let value = Int16(exactly: x) else { return false }
result = value
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Int16 {
var result: Int16?
guard let src = source else { return Int16(0) }
guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Int16(0) }
return result!
}
}
extension UInt16 : _ObjectTypeBridgeable {
@available(swift, deprecated: 4, renamed: "init(truncating:)")
public init(_ number: NSNumber) {
self = number.uint16Value
}
public init(truncating number: NSNumber) {
self = number.uint16Value
}
public init?(exactly number: NSNumber) {
let value = number.uint16Value
guard NSNumber(value: value) == number else { return nil }
self = value
}
public func _bridgeToObjectiveC() -> NSNumber {
return NSNumber(value: self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt16?) {
result = _unconditionallyBridgeFromObjectiveC(x)
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt16?) -> Bool {
guard let value = UInt16(exactly: x) else { return false }
result = value
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> UInt16 {
var result: UInt16?
guard let src = source else { return UInt16(0) }
guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return UInt16(0) }
return result!
}
}
extension Int32 : _ObjectTypeBridgeable {
@available(swift, deprecated: 4, renamed: "init(truncating:)")
public init(_ number: NSNumber) {
self = number.int32Value
}
public init(truncating number: NSNumber) {
self = number.int32Value
}
public init?(exactly number: NSNumber) {
let value = number.int32Value
guard NSNumber(value: value) == number else { return nil }
self = value
}
public func _bridgeToObjectiveC() -> NSNumber {
return NSNumber(value: self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Int32?) {
result = _unconditionallyBridgeFromObjectiveC(x)
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Int32?) -> Bool {
guard let value = Int32(exactly: x) else { return false }
result = value
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Int32 {
var result: Int32?
guard let src = source else { return Int32(0) }
guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Int32(0) }
return result!
}
}
extension UInt32 : _ObjectTypeBridgeable {
@available(swift, deprecated: 4, renamed: "init(truncating:)")
public init(_ number: NSNumber) {
self = number.uint32Value
}
public init(truncating number: NSNumber) {
self = number.uint32Value
}
public init?(exactly number: NSNumber) {
let value = number.uint32Value
guard NSNumber(value: value) == number else { return nil }
self = value
}
public func _bridgeToObjectiveC() -> NSNumber {
return NSNumber(value: self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt32?) {
result = _unconditionallyBridgeFromObjectiveC(x)
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt32?) -> Bool {
guard let value = UInt32(exactly: x) else { return false }
result = value
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> UInt32 {
var result: UInt32?
guard let src = source else { return UInt32(0) }
guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return UInt32(0) }
return result!
}
}
extension Int64 : _ObjectTypeBridgeable {
@available(swift, deprecated: 4, renamed: "init(truncating:)")
public init(_ number: NSNumber) {
self = number.int64Value
}
public init(truncating number: NSNumber) {
self = number.int64Value
}
public init?(exactly number: NSNumber) {
let value = number.int64Value
guard NSNumber(value: value) == number else { return nil }
self = value
}
public func _bridgeToObjectiveC() -> NSNumber {
return NSNumber(value: self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Int64?) {
result = _unconditionallyBridgeFromObjectiveC(x)
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Int64?) -> Bool {
guard let value = Int64(exactly: x) else { return false }
result = value
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Int64 {
var result: Int64?
guard let src = source else { return Int64(0) }
guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Int64(0) }
return result!
}
}
extension UInt64 : _ObjectTypeBridgeable {
@available(swift, deprecated: 4, renamed: "init(truncating:)")
public init(_ number: NSNumber) {
self = number.uint64Value
}
public init(truncating number: NSNumber) {
self = number.uint64Value
}
public init?(exactly number: NSNumber) {
let value = number.uint64Value
guard NSNumber(value: value) == number else { return nil }
self = value
}
public func _bridgeToObjectiveC() -> NSNumber {
return NSNumber(value: self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt64?) {
result = _unconditionallyBridgeFromObjectiveC(x)
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt64?) -> Bool {
guard let value = UInt64(exactly: x) else { return false }
result = value
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> UInt64 {
var result: UInt64?
guard let src = source else { return UInt64(0) }
guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return UInt64(0) }
return result!
}
}
extension Int : _ObjectTypeBridgeable {
@available(swift, deprecated: 4, renamed: "init(truncating:)")
public init(_ number: NSNumber) {
self = number.intValue
}
public init(truncating number: NSNumber) {
self = number.intValue
}
public init?(exactly number: NSNumber) {
let value = number.intValue
guard NSNumber(value: value) == number else { return nil }
self = value
}
public func _bridgeToObjectiveC() -> NSNumber {
return NSNumber(value: self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Int?) {
result = _unconditionallyBridgeFromObjectiveC(x)
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Int?) -> Bool {
guard let value = Int(exactly: x) else { return false }
result = value
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Int {
var result: Int?
guard let src = source else { return Int(0) }
guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Int(0) }
return result!
}
}
extension UInt : _ObjectTypeBridgeable {
@available(swift, deprecated: 4, renamed: "init(truncating:)")
public init(_ number: NSNumber) {
self = number.uintValue
}
public init(truncating number: NSNumber) {
self = number.uintValue
}
public init?(exactly number: NSNumber) {
let value = number.uintValue
guard NSNumber(value: value) == number else { return nil }
self = value
}
public func _bridgeToObjectiveC() -> NSNumber {
return NSNumber(value: self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt?) {
result = _unconditionallyBridgeFromObjectiveC(x)
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout UInt?) -> Bool {
guard let value = UInt(exactly: x) else { return false }
result = value
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> UInt {
var result: UInt?
guard let src = source else { return UInt(0) }
guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return UInt(0) }
return result!
}
}
extension Float : _ObjectTypeBridgeable {
@available(swift, deprecated: 4, renamed: "init(truncating:)")
public init(_ number: NSNumber) {
self = number.floatValue
}
public init(truncating number: NSNumber) {
self = number.floatValue
}
public init?(exactly number: NSNumber) {
guard let value = Double(exactly: number) else { return nil }
guard let result = Float(exactly: value) else { return nil }
self = result
}
public func _bridgeToObjectiveC() -> NSNumber {
return NSNumber(value: self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Float?) {
result = _unconditionallyBridgeFromObjectiveC(x)
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Float?) -> Bool {
guard let value = Double(exactly: x) else { return false }
guard !value.isNaN else {
result = Float.nan
return true
}
guard !value.isInfinite else {
if value.sign == .minus {
result = -Float.infinity
} else {
result = Float.infinity
}
return true
}
guard Swift.abs(value) <= Double(Float.greatestFiniteMagnitude) else {
return false
}
result = Float(value)
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Float {
var result: Float?
guard let src = source else { return Float(0) }
guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Float(0) }
return result!
}
}
extension Double : _ObjectTypeBridgeable {
@available(swift, deprecated: 4, renamed: "init(truncating:)")
public init(_ number: NSNumber) {
self = number.doubleValue
}
public init(truncating number: NSNumber) {
self = number.doubleValue
}
public init?(exactly number: NSNumber) {
let type = number.objCType.pointee
if type == 0x51 {
guard let result = Double(exactly: number.uint64Value) else { return nil }
self = result
} else if type == 0x71 {
guard let result = Double(exactly: number.int64Value) else { return nil }
self = result
} else {
self = number.doubleValue
}
}
public func _bridgeToObjectiveC() -> NSNumber {
return NSNumber(value: self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Double?) {
result = _unconditionallyBridgeFromObjectiveC(x)
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Double?) -> Bool {
guard let value = Double(exactly: x) else { return false }
result = value
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Double {
var result: Double?
guard let src = source else { return Double(0) }
guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return Double(0) }
return result!
}
}
extension Bool : _ObjectTypeBridgeable {
@available(swift, deprecated: 4, renamed: "init(truncating:)")
public init(_ number: NSNumber) {
self = number.boolValue
}
public init(truncating number: NSNumber) {
self = number.boolValue
}
public init?(exactly number: NSNumber) {
if number === kCFBooleanTrue || NSNumber(value: 1) == number {
self = true
} else if number === kCFBooleanFalse || NSNumber(value: 0) == number {
self = false
} else {
return nil
}
}
public func _bridgeToObjectiveC() -> NSNumber {
return unsafeBitCast(self ? kCFBooleanTrue : kCFBooleanFalse, to: NSNumber.self)
}
public static func _forceBridgeFromObjectiveC(_ x: NSNumber, result: inout Bool?) {
result = _unconditionallyBridgeFromObjectiveC(x)
}
public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Bool?) -> Bool {
result = x.boolValue
return true
}
public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Bool {
var result: Bool?
guard let src = source else { return false }
guard _conditionallyBridgeFromObjectiveC(src, result: &result) else { return false }
return result!
}
}
extension Bool : _CFBridgeable {
typealias CFType = CFBoolean
var _cfObject: CFType {
return self ? kCFBooleanTrue : kCFBooleanFalse
}
}
extension NSNumber : ExpressibleByFloatLiteral, ExpressibleByIntegerLiteral, ExpressibleByBooleanLiteral {
}
private struct CFSInt128Struct {
var high: Int64
var low: UInt64
}
open class NSNumber : NSValue {
typealias CFType = CFNumber
// This layout MUST be the same as CFNumber so that they are bridgeable
private var _base = _CFInfo(typeID: CFNumberGetTypeID())
private var _pad: UInt64 = 0
internal var _cfObject: CFType {
return unsafeBitCast(self, to: CFType.self)
}
open override var hash: Int {
return Int(bitPattern: CFHash(_cfObject))
}
open override func isEqual(_ value: Any?) -> Bool {
switch value {
case let other as Int:
return intValue == other
case let other as Double:
return doubleValue == other
case let other as Bool:
return boolValue == other
case let other as NSNumber:
return compare(other) == .orderedSame
default:
return false
}
}
open override var objCType: UnsafePointer<Int8> {
func _objCType(_ staticString: StaticString) -> UnsafePointer<Int8> {
return UnsafeRawPointer(staticString.utf8Start).assumingMemoryBound(to: Int8.self)
}
let numberType = _CFNumberGetType2(_cfObject)
switch numberType {
case kCFNumberSInt8Type:
return _objCType("c")
case kCFNumberSInt16Type:
return _objCType("s")
case kCFNumberSInt32Type:
return _objCType("i")
case kCFNumberSInt64Type:
return _objCType("q")
case kCFNumberFloat32Type:
return _objCType("f")
case kCFNumberFloat64Type:
return _objCType("d")
case kCFNumberSInt128Type:
return _objCType("Q")
default:
fatalError("unsupported CFNumberType: '\(numberType)'")
}
}
deinit {
_CFDeinit(self)
}
private convenience init(bytes: UnsafeRawPointer, numberType: CFNumberType) {
let cfnumber = CFNumberCreate(nil, numberType, bytes)
self.init(factory: { unsafeBitCast(cfnumber, to: NSNumber.self) })
}
public convenience init(value: Int8) {
var value = value
self.init(bytes: &value, numberType: kCFNumberSInt8Type)
}
public convenience init(value: UInt8) {
var value = Int16(value)
self.init(bytes: &value, numberType: kCFNumberSInt16Type)
}
public convenience init(value: Int16) {
var value = value
self.init(bytes: &value, numberType: kCFNumberSInt16Type)
}
public convenience init(value: UInt16) {
var value = Int32(value)
self.init(bytes: &value, numberType: kCFNumberSInt32Type)
}
public convenience init(value: Int32) {
var value = value
self.init(bytes: &value, numberType: kCFNumberSInt32Type)
}
public convenience init(value: UInt32) {
var value = Int64(value)
self.init(bytes: &value, numberType: kCFNumberSInt64Type)
}
public convenience init(value: Int) {
var value = value
#if arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
self.init(bytes: &value, numberType: kCFNumberSInt64Type)
#elseif arch(i386) || arch(arm)
self.init(bytes: &value, numberType: kCFNumberSInt32Type)
#endif
}
public convenience init(value: UInt) {
#if arch(x86_64) || arch(arm64) || arch(s390x) || arch(powerpc64) || arch(powerpc64le)
if value > UInt64(Int64.max) {
var value = CFSInt128Struct(high: 0, low: UInt64(value))
self.init(bytes: &value, numberType: kCFNumberSInt128Type)
} else {
var value = Int64(value)
self.init(bytes: &value, numberType: kCFNumberSInt64Type)
}
#elseif arch(i386) || arch(arm)
var value = Int64(value)
self.init(bytes: &value, numberType: kCFNumberSInt64Type)
#endif
}
public convenience init(value: Int64) {
var value = value
self.init(bytes: &value, numberType: kCFNumberSInt64Type)
}
public convenience init(value: UInt64) {
if value > UInt64(Int64.max) {
var value = CFSInt128Struct(high: 0, low: UInt64(value))
self.init(bytes: &value, numberType: kCFNumberSInt128Type)
} else {
var value = Int64(value)
self.init(bytes: &value, numberType: kCFNumberSInt64Type)
}
}
public convenience init(value: Float) {
var value = value
self.init(bytes: &value, numberType: kCFNumberFloatType)
}
public convenience init(value: Double) {
var value = value
self.init(bytes: &value, numberType: kCFNumberDoubleType)
}
public convenience init(value: Bool) {
self.init(factory: value._bridgeToObjectiveC)
}
override internal init() {
super.init()
}
public required convenience init(bytes buffer: UnsafeRawPointer, objCType: UnsafePointer<Int8>) {
guard let type = _NSSimpleObjCType(UInt8(objCType.pointee)) else {
fatalError("NSNumber.init: unsupported type encoding spec '\(String(cString: objCType))'")
}
switch type {
case .Bool:
self.init(value:buffer.load(as: Bool.self))
case .Char:
self.init(value:buffer.load(as: Int8.self))
case .UChar:
self.init(value:buffer.load(as: UInt8.self))
case .Short:
self.init(value:buffer.load(as: Int16.self))
case .UShort:
self.init(value:buffer.load(as: UInt16.self))
case .Int, .Long:
self.init(value:buffer.load(as: Int32.self))
case .UInt, .ULong:
self.init(value:buffer.load(as: UInt32.self))
case .LongLong:
self.init(value:buffer.load(as: Int64.self))
case .ULongLong:
self.init(value:buffer.load(as: UInt64.self))
case .Float:
self.init(value:buffer.load(as: Float.self))
case .Double:
self.init(value:buffer.load(as: Double.self))
default:
fatalError("NSNumber.init: unsupported type encoding spec '\(String(cString: objCType))'")
}
}
public required convenience init?(coder aDecoder: NSCoder) {
guard aDecoder.allowsKeyedCoding else {
preconditionFailure("Unkeyed coding is unsupported.")
}
if type(of: aDecoder) == NSKeyedUnarchiver.self || aDecoder.containsValue(forKey: "NS.number") {
let number = aDecoder._decodePropertyListForKey("NS.number")
if let val = number as? Double {
self.init(value:val)
} else if let val = number as? Int {
self.init(value:val)
} else if let val = number as? Bool {
self.init(value:val)
} else {
return nil
}
} else {
if aDecoder.containsValue(forKey: "NS.boolval") {
self.init(value: aDecoder.decodeBool(forKey: "NS.boolval"))
} else if aDecoder.containsValue(forKey: "NS.intval") {
self.init(value: aDecoder.decodeInt64(forKey: "NS.intval"))
} else if aDecoder.containsValue(forKey: "NS.dblval") {
self.init(value: aDecoder.decodeDouble(forKey: "NS.dblval"))
} else {
return nil
}
}
}
open var int8Value: Int8 {
var value: Int64 = 0
CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
return .init(truncatingIfNeeded: value)
}
open var uint8Value: UInt8 {
var value: Int64 = 0
CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
return .init(truncatingIfNeeded: value)
}
open var int16Value: Int16 {
var value: Int64 = 0
CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
return .init(truncatingIfNeeded: value)
}
open var uint16Value: UInt16 {
var value: Int64 = 0
CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
return .init(truncatingIfNeeded: value)
}
open var int32Value: Int32 {
var value: Int64 = 0
CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
return .init(truncatingIfNeeded: value)
}
open var uint32Value: UInt32 {
var value: Int64 = 0
CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
return .init(truncatingIfNeeded: value)
}
open var int64Value: Int64 {
var value: Int64 = 0
CFNumberGetValue(_cfObject, kCFNumberSInt64Type, &value)
return .init(truncatingIfNeeded: value)
}
open var uint64Value: UInt64 {
var value = CFSInt128Struct(high: 0, low: 0)
CFNumberGetValue(_cfObject, kCFNumberSInt128Type, &value)
return .init(truncatingIfNeeded: value.low)
}
private var int128Value: CFSInt128Struct {
var value = CFSInt128Struct(high: 0, low: 0)
CFNumberGetValue(_cfObject, kCFNumberSInt128Type, &value)
return value
}
open var floatValue: Float {
var value: Float = 0
CFNumberGetValue(_cfObject, kCFNumberFloatType, &value)
return value
}
open var doubleValue: Double {
var value: Double = 0
CFNumberGetValue(_cfObject, kCFNumberDoubleType, &value)
return value
}
open var boolValue: Bool {
// Darwin Foundation NSNumber appears to have a bug and return false for NSNumber(value: Int64.min).boolValue,
// even though the documentation says:
// "A 0 value always means false, and any nonzero value is interpreted as true."
return (int64Value != 0) && (int64Value != Int64.min)
}
open var intValue: Int {
var val: Int = 0
withUnsafeMutablePointer(to: &val) { (value: UnsafeMutablePointer<Int>) -> Void in
CFNumberGetValue(_cfObject, kCFNumberLongType, value)
}
return val
}
open var uintValue: UInt {
var val: UInt = 0
withUnsafeMutablePointer(to: &val) { (value: UnsafeMutablePointer<UInt>) -> Void in
CFNumberGetValue(_cfObject, kCFNumberLongType, value)
}
return val
}
open var stringValue: String {
return description(withLocale: nil)
}
/// Create an instance initialized to `value`.
public required convenience init(integerLiteral value: Int) {
self.init(value: value)
}
/// Create an instance initialized to `value`.
public required convenience init(floatLiteral value: Double) {
self.init(value: value)
}
/// Create an instance initialized to `value`.
public required convenience init(booleanLiteral value: Bool) {
self.init(value: value)
}
open func compare(_ otherNumber: NSNumber) -> ComparisonResult {
switch (_cfNumberType(), otherNumber._cfNumberType()) {
case (kCFNumberFloatType, _), (_, kCFNumberFloatType): fallthrough
case (kCFNumberDoubleType, _), (_, kCFNumberDoubleType):
let (lhs, rhs) = (doubleValue, otherNumber.doubleValue)
// Apply special handling for NaN as <, >, == always return false
// when comparing with NaN
if lhs.isNaN && rhs.isNaN { return .orderedSame }
if lhs.isNaN { return .orderedAscending }
if rhs.isNaN { return .orderedDescending }
if lhs < rhs { return .orderedAscending }
if lhs > rhs { return .orderedDescending }
return .orderedSame
default: // For signed and unsigned integers expand upto S128Int
let (lhs, rhs) = (int128Value, otherNumber.int128Value)
if lhs.high < rhs.high { return .orderedAscending }
if lhs.high > rhs.high { return .orderedDescending }
if lhs.low < rhs.low { return .orderedAscending }
if lhs.low > rhs.low { return .orderedDescending }
return .orderedSame
}
}
private static let _numberFormatterForNilLocale: CFNumberFormatter = {
let formatter: CFNumberFormatter
formatter = CFNumberFormatterCreate(nil, CFLocaleCopyCurrent(), kCFNumberFormatterNoStyle)
CFNumberFormatterSetProperty(formatter, kCFNumberFormatterMaxFractionDigits, 15._bridgeToObjectiveC())
return formatter
}()
open func description(withLocale locale: Locale?) -> String {
// CFNumberFormatterCreateStringWithNumber() does not like numbers of type
// SInt128Type, as it loses the type when looking it up and treats it as
// an SInt64Type, so special case them.
if _CFNumberGetType2(_cfObject) == kCFNumberSInt128Type {
return String(format: "%@", unsafeBitCast(_cfObject, to: UnsafePointer<CFNumber>.self))
}
let aLocale = locale
let formatter: CFNumberFormatter
if (aLocale == nil) {
formatter = NSNumber._numberFormatterForNilLocale
} else {
formatter = CFNumberFormatterCreate(nil, aLocale?._cfObject, kCFNumberFormatterDecimalStyle)
}
return CFNumberFormatterCreateStringWithNumber(nil, formatter, self._cfObject)._swiftObject
}
override open var _cfTypeID: CFTypeID {
return CFNumberGetTypeID()
}
open override var description: String {
return description(withLocale: nil)
}
internal func _cfNumberType() -> CFNumberType {
switch objCType.pointee {
case 0x42: return kCFNumberCharType
case 0x63: return kCFNumberCharType
case 0x43: return kCFNumberShortType
case 0x73: return kCFNumberShortType
case 0x53: return kCFNumberIntType
case 0x69: return kCFNumberIntType
case 0x49: return Int(uint32Value) < Int(Int32.max) ? kCFNumberIntType : kCFNumberLongLongType
case 0x6C: return kCFNumberLongType
case 0x4C: return uintValue < UInt(Int.max) ? kCFNumberLongType : kCFNumberLongLongType
case 0x66: return kCFNumberFloatType
case 0x64: return kCFNumberDoubleType
case 0x71: return kCFNumberLongLongType
case 0x51: return kCFNumberLongLongType
default: fatalError()
}
}
internal func _getValue(_ valuePtr: UnsafeMutableRawPointer, forType type: CFNumberType) -> Bool {
switch type {
case kCFNumberSInt8Type:
valuePtr.assumingMemoryBound(to: Int8.self).pointee = int8Value
break
case kCFNumberSInt16Type:
valuePtr.assumingMemoryBound(to: Int16.self).pointee = int16Value
break
case kCFNumberSInt32Type:
valuePtr.assumingMemoryBound(to: Int32.self).pointee = int32Value
break
case kCFNumberSInt64Type:
valuePtr.assumingMemoryBound(to: Int64.self).pointee = int64Value
break
case kCFNumberSInt128Type:
struct CFSInt128Struct {
var high: Int64
var low: UInt64
}
let val = int64Value
valuePtr.assumingMemoryBound(to: CFSInt128Struct.self).pointee = CFSInt128Struct.init(high: (val < 0) ? -1 : 0, low: UInt64(bitPattern: val))
break
case kCFNumberFloat32Type:
valuePtr.assumingMemoryBound(to: Float.self).pointee = floatValue
break
case kCFNumberFloat64Type:
valuePtr.assumingMemoryBound(to: Double.self).pointee = doubleValue
default: fatalError()
}
return true
}
open override func encode(with aCoder: NSCoder) {
guard aCoder.allowsKeyedCoding else {
preconditionFailure("Unkeyed coding is unsupported.")
}
if let keyedCoder = aCoder as? NSKeyedArchiver {
keyedCoder._encodePropertyList(self)
} else {
if CFGetTypeID(self) == CFBooleanGetTypeID() {
aCoder.encode(boolValue, forKey: "NS.boolval")
} else {
switch objCType.pointee {
case 0x42:
aCoder.encode(boolValue, forKey: "NS.boolval")
break
case 0x63: fallthrough
case 0x43: fallthrough
case 0x73: fallthrough
case 0x53: fallthrough
case 0x69: fallthrough
case 0x49: fallthrough
case 0x6C: fallthrough
case 0x4C: fallthrough
case 0x71: fallthrough
case 0x51:
aCoder.encode(int64Value, forKey: "NS.intval")
case 0x66: fallthrough
case 0x64:
aCoder.encode(doubleValue, forKey: "NS.dblval")
default: break
}
}
}
}
open override var classForCoder: AnyClass { return NSNumber.self }
}
extension CFNumber : _NSBridgeable {
typealias NSType = NSNumber
internal var _nsObject: NSType { return unsafeBitCast(self, to: NSType.self) }
}
internal func _CFSwiftNumberGetType(_ obj: CFTypeRef) -> CFNumberType {
return unsafeBitCast(obj, to: NSNumber.self)._cfNumberType()
}
internal func _CFSwiftNumberGetValue(_ obj: CFTypeRef, _ valuePtr: UnsafeMutableRawPointer, _ type: CFNumberType) -> Bool {
return unsafeBitCast(obj, to: NSNumber.self)._getValue(valuePtr, forType: type)
}
internal func _CFSwiftNumberGetBoolValue(_ obj: CFTypeRef) -> Bool {
return unsafeBitCast(obj, to: NSNumber.self).boolValue
}