Skip to content

Commit 82b3bd7

Browse files
committed
Account for kCFBooleanTrue and kCFBooleanFalse being present in bridged payloads
This converts kCFBooleanTrue and kCFBooleanFalse into true and false and adds subclassing callout hooks for CFNumber to invoke swift routines.
1 parent 3c737c9 commit 82b3bd7

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)