Skip to content

Commit 4d0880f

Browse files
authored
Merge pull request #909 from phausler/boolean_bridge
2 parents 3c737c9 + 82b3bd7 commit 4d0880f

File tree

12 files changed

+248
-8
lines changed

12 files changed

+248
-8
lines changed

CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,12 @@ struct _NSMutableCharacterSetBridge {
224224
void (*_Nonnull invert)(CFTypeRef cset);
225225
};
226226

227+
struct _NSNumberBridge {
228+
CFNumberType (*_Nonnull _cfNumberGetType)(CFTypeRef number);
229+
bool (*_Nonnull boolValue)(CFTypeRef number);
230+
bool (*_Nonnull _getValue)(CFTypeRef number, void *value, CFNumberType type);
231+
};
232+
227233
struct _CFSwiftBridge {
228234
struct _NSObjectBridge NSObject;
229235
struct _NSArrayBridge NSArray;
@@ -238,6 +244,7 @@ struct _CFSwiftBridge {
238244
struct _NSRunLoop NSRunLoop;
239245
struct _NSCharacterSetBridge NSCharacterSet;
240246
struct _NSMutableCharacterSetBridge NSMutableCharacterSet;
247+
struct _NSNumberBridge NSNumber;
241248
};
242249

243250
CF_EXPORT struct _CFSwiftBridge __CFSwiftBridge;

CoreFoundation/NumberDate.subproj/CFNumber.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ CFTypeID CFBooleanGetTypeID(void) {
8282

8383
Boolean CFBooleanGetValue(CFBooleanRef boolean) {
8484
CF_OBJC_FUNCDISPATCHV(CFBooleanGetTypeID(), Boolean, (NSNumber *)boolean, boolValue);
85+
CF_SWIFT_FUNCDISPATCHV(CFBooleanGetTypeID(), Boolean, (CFSwiftRef)boolean, NSNumber.boolValue);
8586
return (boolean == kCFBooleanTrue) ? true : false;
8687
}
8788

@@ -1063,6 +1064,10 @@ CF_PRIVATE void __CFNumberInitialize(void) {
10631064
_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFNumberFloat64One, __kCFNumberTypeID);
10641065
__CFBitfieldSetValue(__kCFNumberFloat64One._base._cfinfo[CF_INFO_BITS], 4, 0, kCFNumberFloat64Type);
10651066
__kCFNumberFloat64One._pad = BITSFORDOUBLEONE;
1067+
#if DEPLOYMENT_RUNTIME_SWIFT
1068+
_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFBooleanTrue, __kCFBooleanTypeID);
1069+
_CFRuntimeSetInstanceTypeIDAndIsa(& __kCFBooleanFalse, __kCFBooleanTypeID);
1070+
#endif
10661071
}
10671072

10681073
CFTypeID CFNumberGetTypeID(void) {
@@ -1256,6 +1261,7 @@ CFLog(kCFLogLevelWarning, CFSTR("+++ Create old number '%@'"), __CFNumberCopyDes
12561261
CFNumberType CFNumberGetType(CFNumberRef number) {
12571262
//printf("+ [%p] CFNumberGetType(%p)\n", pthread_self(), number);
12581263
CF_OBJC_FUNCDISPATCHV(CFNumberGetTypeID(), CFNumberType, (NSNumber *)number, _cfNumberType);
1264+
CF_SWIFT_FUNCDISPATCHV(CFNumberGetTypeID(), CFNumberType, (CFSwiftRef)number, NSNumber._cfNumberGetType);
12591265
__CFAssertIsNumber(number);
12601266
CFNumberType type = __CFNumberGetType(number);
12611267
if (kCFNumberSInt128Type == type) type = kCFNumberSInt64Type; // must hide this type, since it is not public
@@ -1275,6 +1281,7 @@ CFLog(kCFLogLevelWarning, CFSTR("*** TEST FAIL in CFNumberGetType: '%d' '%d'"),
12751281

12761282
CF_EXPORT CFNumberType _CFNumberGetType2(CFNumberRef number) {
12771283
CF_OBJC_FUNCDISPATCHV(CFNumberGetTypeID(), CFNumberType, (NSNumber *)number, _cfNumberType);
1284+
CF_SWIFT_FUNCDISPATCHV(CFNumberGetTypeID(), CFNumberType, (CFSwiftRef)number, NSNumber._cfNumberGetType);
12781285
__CFAssertIsNumber(number);
12791286
return __CFNumberGetType(number);
12801287
}
@@ -1319,6 +1326,7 @@ Boolean CFNumberGetValue(CFNumberRef number, CFNumberType type, void *valuePtr)
13191326
//printf("+ [%p] CFNumberGetValue(%p, %d, %p)\n", pthread_self(), number, type, valuePtr);
13201327

13211328
CF_OBJC_FUNCDISPATCHV(CFNumberGetTypeID(), Boolean, (NSNumber *)number, _getValue:(void *)valuePtr forType:(CFNumberType)__CFNumberTypeTable[type].canonicalType);
1329+
CF_SWIFT_FUNCDISPATCHV(CFNumberGetTypeID(), Boolean, (CFSwiftRef)number, NSNumber._getValue, valuePtr, (CFNumberType)__CFNumberTypeTable[type].canonicalType);
13221330
__CFAssertIsNumber(number);
13231331
__CFAssertIsValidNumberType(type);
13241332
uint8_t localMemory[128];

Foundation.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
5B40F9F01C125011000E72E3 /* CFXMLInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B40F9EC1C124F45000E72E3 /* CFXMLInterface.h */; settings = {ATTRIBUTES = (Private, ); }; };
9393
5B40F9F41C12524C000E72E3 /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B40F9F31C12524C000E72E3 /* libxml2.dylib */; };
9494
5B424C761D0B6E5B007B39C8 /* IndexPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B424C751D0B6E5B007B39C8 /* IndexPath.swift */; };
95+
5B5BFEAC1E6CC0C200AC8D9E /* NSCFBoolean.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5BFEAB1E6CC0C200AC8D9E /* NSCFBoolean.swift */; };
9596
5B5C5EF01CE61FA4001346BD /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5C5EEF1CE61FA4001346BD /* Date.swift */; };
9697
5B5D89761BBDADD300234F36 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B5D89751BBDADD300234F36 /* libicucore.dylib */; };
9798
5B5D89781BBDADDB00234F36 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B5D89771BBDADDB00234F36 /* libz.dylib */; };
@@ -507,6 +508,7 @@
507508
5B40F9F11C125187000E72E3 /* TestNSXMLParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSXMLParser.swift; sourceTree = "<group>"; };
508509
5B40F9F31C12524C000E72E3 /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = usr/lib/libxml2.dylib; sourceTree = SDKROOT; };
509510
5B424C751D0B6E5B007B39C8 /* IndexPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IndexPath.swift; sourceTree = "<group>"; };
511+
5B5BFEAB1E6CC0C200AC8D9E /* NSCFBoolean.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSCFBoolean.swift; sourceTree = "<group>"; };
510512
5B5C5EEF1CE61FA4001346BD /* Date.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Date.swift; sourceTree = "<group>"; };
511513
5B5D885D1BBC938800234F36 /* SwiftFoundation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftFoundation.framework; sourceTree = BUILT_PRODUCTS_DIR; };
512514
5B5D886A1BBC948300234F36 /* CFApplicationPreferences.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = CFApplicationPreferences.c; sourceTree = "<group>"; };
@@ -1633,6 +1635,7 @@
16331635
5B7818591D6CB5CD004A01F2 /* CGFloat.swift */,
16341636
EADE0B4D1BD09E0800C49C64 /* NSAffineTransform.swift */,
16351637
5BDC3F3D1BCC5DCB00ED97BB /* NSNumber.swift */,
1638+
5B5BFEAB1E6CC0C200AC8D9E /* NSCFBoolean.swift */,
16361639
D31302001C30CEA900295652 /* NSConcreteValue.swift */,
16371640
D3E8D6D01C367AB600295652 /* NSSpecialValue.swift */,
16381641
5BDC3F4C1BCC5DCB00ED97BB /* NSValue.swift */,
@@ -2077,6 +2080,7 @@
20772080
5B1FD9D61D6D16580080E83C /* HTTPBodySource.swift in Sources */,
20782081
EADE0BB21BD15E0000C49C64 /* Progress.swift in Sources */,
20792082
EADE0B961BD15DFF00C49C64 /* NSDateIntervalFormatter.swift in Sources */,
2083+
5B5BFEAC1E6CC0C200AC8D9E /* NSCFBoolean.swift in Sources */,
20802084
6EB768281D18C12C00D4B719 /* UUID.swift in Sources */,
20812085
5B1FD9D41D6D16580080E83C /* Configuration.swift in Sources */,
20822086
5BF7AEA51BCD51F9008F214A /* NSCalendar.swift in Sources */,

Foundation/Bridging.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
import CoreFoundation
14+
1315
// Support protocols for casting
1416
public protocol _ObjectBridgeable {
1517
func _bridgeToAnyObject() -> AnyObject
@@ -83,7 +85,11 @@ internal final class _SwiftValue : NSObject, NSCopying {
8385
}
8486

8587
static func fetch(nonOptional object: AnyObject) -> Any {
86-
if let container = object as? _SwiftValue {
88+
if object === kCFBooleanTrue {
89+
return true
90+
} else if object === kCFBooleanFalse {
91+
return false
92+
} else if let container = object as? _SwiftValue {
8793
return container.value
8894
} else if let val = object as? _StructBridgeable {
8995
return val._bridgeToAny()

Foundation/NSCFBoolean.swift

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// This source file is part of the Swift.org open source project
2+
//
3+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
4+
// Licensed under Apache License v2.0 with Runtime Library Exception
5+
//
6+
// See http://swift.org/LICENSE.txt for license information
7+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
8+
//
9+
10+
11+
import CoreFoundation
12+
13+
internal class __NSCFBoolean : NSNumber {
14+
override var hash: Int {
15+
return Int(bitPattern: CFHash(unsafeBitCast(self, to: CFBoolean.self)))
16+
}
17+
18+
override func description(withLocale locale: Locale?) -> String {
19+
return boolValue ? "1" : "0"
20+
}
21+
22+
override var int8Value: Int8 {
23+
return boolValue ? 1 : 0
24+
}
25+
26+
override var uint8Value: UInt8 {
27+
return boolValue ? 1 : 0
28+
}
29+
30+
override var int16Value: Int16 {
31+
return boolValue ? 1 : 0
32+
}
33+
34+
override var uint16Value: UInt16 {
35+
return boolValue ? 1 : 0
36+
}
37+
38+
override var int32Value: Int32 {
39+
return boolValue ? 1 : 0
40+
}
41+
42+
override var uint32Value: UInt32 {
43+
return boolValue ? 1 : 0
44+
}
45+
46+
override var intValue: Int {
47+
return boolValue ? 1 : 0
48+
}
49+
50+
override var uintValue: UInt {
51+
return boolValue ? 1 : 0
52+
}
53+
54+
override var int64Value: Int64 {
55+
return boolValue ? 1 : 0
56+
}
57+
58+
override var uint64Value: UInt64 {
59+
return boolValue ? 1 : 0
60+
}
61+
62+
override var floatValue: Float {
63+
return boolValue ? 1 : 0
64+
}
65+
66+
override var doubleValue: Double {
67+
return boolValue ? 1 : 0
68+
}
69+
70+
override var boolValue: Bool {
71+
return CFBooleanGetValue(unsafeBitCast(self, to: CFBoolean.self))
72+
}
73+
74+
override var _cfTypeID: CFTypeID {
75+
return CFBooleanGetTypeID()
76+
}
77+
78+
override var objCType: UnsafePointer<Int8> {
79+
// This must never be fixed to be "B", although that would
80+
// cause correct old-style archiving when this is unarchived.
81+
return UnsafePointer<Int8>(bitPattern: UInt(_NSSimpleObjCType.Char.rawValue.value))!
82+
}
83+
84+
internal override func _cfNumberType() -> CFNumberType {
85+
return kCFNumberCharType
86+
}
87+
}

Foundation/NSCoder.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ open class NSCoder : NSObject {
720720
NSRequiresConcreteImplementation()
721721
}
722722

723-
internal func _decodePropertyListForKey(_ key: String) -> Any {
723+
internal func _decodePropertyListForKey(_ key: String) -> Any? {
724724
NSRequiresConcreteImplementation()
725725
}
726726
}

Foundation/NSKeyedArchiver.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ open class NSKeyedArchiver : NSCoder {
460460
guard let obj = objv else { return false }
461461
if obj is String { return false }
462462
guard let nsObject = obj as? NSObject else { return true }
463-
return !(type(of: nsObject) === NSString.self || type(of: nsObject) === NSNumber.self || type(of: nsObject) === NSData.self)
463+
return !(nsObject.classForCoder === NSString.self || nsObject.classForCoder === NSNumber.self || nsObject.classForCoder === NSData.self)
464464
}
465465

466466
/**

Foundation/NSKeyedUnarchiver.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -675,11 +675,11 @@ open class NSKeyedUnarchiver : NSCoder {
675675

676676
/**
677677
Note that unlike decodePropertyList(forKey:), _decodePropertyListForKey() decodes
678-
a property list in the current decoding context rather than as an object. It's
679-
also able to return value types.
678+
a property list in the current decoding context rather than as an object. It also
679+
is able to return value types.
680680
*/
681-
internal override func _decodePropertyListForKey(_ key: String) -> Any {
682-
return _decodeValue(forKey: key)!
681+
internal override func _decodePropertyListForKey(_ key: String) -> Any? {
682+
return _decodeValue(forKey: key)
683683
}
684684

685685
open override func decodeBool(forKey key: String) -> Bool {

Foundation/NSNumber.swift

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ internal let kCFNumberDoubleType = CFNumberType.doubleType
2727
internal let kCFNumberCFIndexType = CFNumberType.cfIndexType
2828
internal let kCFNumberNSIntegerType = CFNumberType.nsIntegerType
2929
internal let kCFNumberCGFloatType = CFNumberType.cgFloatType
30+
internal let kCFNumberSInt128Type = CFNumberType(rawValue: 17)!
31+
#else
32+
internal let kCFNumberSInt128Type: CFNumberType = 17
3033
#endif
3134

3235
extension Int : _ObjectTypeBridgeable {
@@ -160,7 +163,7 @@ extension Bool : _ObjectTypeBridgeable {
160163

161164
public typealias _ObjectType = NSNumber
162165
public func _bridgeToObjectiveC() -> _ObjectType {
163-
return NSNumber(value: self)
166+
return unsafeBitCast(self ? kCFBooleanTrue : kCFBooleanFalse, to: NSNumber.self)
164167
}
165168

166169
static public func _forceBridgeFromObjectiveC(_ source: _ObjectType, result: inout Bool?) {
@@ -520,10 +523,109 @@ open class NSNumber : NSValue {
520523
open override var description: String {
521524
return description(withLocale: nil)
522525
}
526+
527+
internal func _cfNumberType() -> CFNumberType {
528+
switch objCType.pointee {
529+
case 0x42: return kCFNumberCharType
530+
case 0x63: return kCFNumberCharType
531+
case 0x43: return kCFNumberShortType
532+
case 0x73: return kCFNumberShortType
533+
case 0x53: return kCFNumberIntType
534+
case 0x69: return kCFNumberIntType
535+
case 0x49: return Int(uint32Value) < Int(Int32.max) ? kCFNumberIntType : kCFNumberLongLongType
536+
case 0x6C: return kCFNumberLongType
537+
case 0x4C: return uintValue < UInt(Int.max) ? kCFNumberLongType : kCFNumberLongLongType
538+
case 0x66: return kCFNumberFloatType
539+
case 0x64: return kCFNumberDoubleType
540+
case 0x71: return kCFNumberLongLongType
541+
case 0x51: return kCFNumberLongLongType
542+
default: fatalError()
543+
}
544+
}
545+
546+
internal func _getValue(_ valuePtr: UnsafeMutableRawPointer, forType type: CFNumberType) -> Bool {
547+
switch type {
548+
case kCFNumberSInt8Type:
549+
valuePtr.assumingMemoryBound(to: Int8.self).pointee = int8Value
550+
break
551+
case kCFNumberSInt16Type:
552+
valuePtr.assumingMemoryBound(to: Int16.self).pointee = int16Value
553+
break
554+
case kCFNumberSInt32Type:
555+
valuePtr.assumingMemoryBound(to: Int32.self).pointee = int32Value
556+
break
557+
case kCFNumberSInt64Type:
558+
valuePtr.assumingMemoryBound(to: Int64.self).pointee = int64Value
559+
break
560+
case kCFNumberSInt128Type:
561+
struct CFSInt128Struct {
562+
var high: Int64
563+
var low: UInt64
564+
}
565+
let val = int64Value
566+
valuePtr.assumingMemoryBound(to: CFSInt128Struct.self).pointee = CFSInt128Struct.init(high: (val < 0) ? -1 : 0, low: UInt64(bitPattern: val))
567+
break
568+
case kCFNumberFloat32Type:
569+
valuePtr.assumingMemoryBound(to: Float.self).pointee = floatValue
570+
break
571+
case kCFNumberFloat64Type:
572+
valuePtr.assumingMemoryBound(to: Double.self).pointee = doubleValue
573+
default: fatalError()
574+
}
575+
return true
576+
}
577+
578+
open override func encode(with aCoder: NSCoder) {
579+
if !aCoder.allowsKeyedCoding {
580+
NSUnimplemented()
581+
} else {
582+
if let keyedCoder = aCoder as? NSKeyedArchiver {
583+
keyedCoder._encodePropertyList(self)
584+
} else {
585+
if CFGetTypeID(self) == CFBooleanGetTypeID() {
586+
aCoder.encode(boolValue, forKey: "NS.boolval")
587+
} else {
588+
switch objCType.pointee {
589+
case 0x42:
590+
aCoder.encode(boolValue, forKey: "NS.boolval")
591+
break
592+
case 0x63: fallthrough
593+
case 0x43: fallthrough
594+
case 0x73: fallthrough
595+
case 0x53: fallthrough
596+
case 0x69: fallthrough
597+
case 0x49: fallthrough
598+
case 0x6C: fallthrough
599+
case 0x4C: fallthrough
600+
case 0x71: fallthrough
601+
case 0x51:
602+
aCoder.encode(int64Value, forKey: "NS.intval")
603+
case 0x66: fallthrough
604+
case 0x64:
605+
aCoder.encode(doubleValue, forKey: "NS.dblval")
606+
default: break
607+
}
608+
}
609+
}
610+
}
611+
}
612+
613+
open override var classForCoder: AnyClass { return NSNumber.self }
523614
}
524615

525616
extension CFNumber : _NSBridgeable {
526617
typealias NSType = NSNumber
527618
internal var _nsObject: NSType { return unsafeBitCast(self, to: NSType.self) }
528619
}
529620

621+
internal func _CFSwiftNumberGetType(_ obj: CFTypeRef) -> CFNumberType {
622+
return unsafeBitCast(obj, to: NSNumber.self)._cfNumberType()
623+
}
624+
625+
internal func _CFSwiftNumberGetValue(_ obj: CFTypeRef, _ valuePtr: UnsafeMutableRawPointer, _ type: CFNumberType) -> Bool {
626+
return unsafeBitCast(obj, to: NSNumber.self)._getValue(valuePtr, forType: type)
627+
}
628+
629+
internal func _CFSwiftNumberGetBoolValue(_ obj: CFTypeRef) -> Bool {
630+
return unsafeBitCast(obj, to: NSNumber.self).boolValue
631+
}

Foundation/NSSwiftRuntime.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ internal func __CFInitializeSwift() {
9090
_CFRuntimeBridgeTypeToClass(CFArrayGetTypeID(), unsafeBitCast(_NSCFArray.self, to: UnsafeRawPointer.self))
9191
_CFRuntimeBridgeTypeToClass(CFDictionaryGetTypeID(), unsafeBitCast(_NSCFDictionary.self, to: UnsafeRawPointer.self))
9292
_CFRuntimeBridgeTypeToClass(CFSetGetTypeID(), unsafeBitCast(_NSCFSet.self, to: UnsafeRawPointer.self))
93+
_CFRuntimeBridgeTypeToClass(CFBooleanGetTypeID(), unsafeBitCast(__NSCFBoolean.self, to: UnsafeRawPointer.self))
9394
_CFRuntimeBridgeTypeToClass(CFNumberGetTypeID(), unsafeBitCast(NSNumber.self, to: UnsafeRawPointer.self))
9495
_CFRuntimeBridgeTypeToClass(CFDataGetTypeID(), unsafeBitCast(NSData.self, to: UnsafeRawPointer.self))
9596
_CFRuntimeBridgeTypeToClass(CFDateGetTypeID(), unsafeBitCast(NSDate.self, to: UnsafeRawPointer.self))
@@ -217,6 +218,10 @@ internal func __CFInitializeSwift() {
217218
__CFSwiftBridge.NSMutableCharacterSet.formIntersectionWithCharacterSet = _CFSwiftMutableSetFormIntersectionWithCharacterSet
218219
__CFSwiftBridge.NSMutableCharacterSet.invert = _CFSwiftMutableSetInvert
219220

221+
__CFSwiftBridge.NSNumber._cfNumberGetType = _CFSwiftNumberGetType
222+
__CFSwiftBridge.NSNumber._getValue = _CFSwiftNumberGetValue
223+
__CFSwiftBridge.NSNumber.boolValue = _CFSwiftNumberGetBoolValue
224+
220225
// __CFDefaultEightBitStringEncoding = UInt32(kCFStringEncodingUTF8)
221226
}
222227

0 commit comments

Comments
 (0)