Skip to content

Commit 0fa5580

Browse files
committed
Parity: NSCoding: NSIndexSet
- Bridge NSData fully to CF. Work around the fact that NSData has a mutable subclass. - Implement NS{Mutable,}IndexSet encoding and decoding.
1 parent cef3bbd commit 0fa5580

15 files changed

+314
-65
lines changed

CoreFoundation/Base.subproj/CFInternal.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -788,11 +788,12 @@ extern void _CFRuntimeSetInstanceTypeIDAndIsa(CFTypeRef cf, CFTypeID newTypeID);
788788
#if DEPLOYMENT_RUNTIME_SWIFT
789789
#define CF_IS_SWIFT(type, obj) (_CFIsSwift(type, (CFSwiftRef)obj))
790790

791-
#define CF_SWIFT_FUNCDISPATCHV(type, ret, obj, fn, ...) do { \
792-
if (CF_IS_SWIFT(type, obj)) { \
791+
#define CF_SWIFT_FUNCDISPATCHV_CHECK(check, type, ret, obj, fn, ...) do { \
792+
if (check(type, obj)) { \
793793
return (ret)__CFSwiftBridge.fn((CFSwiftRef)obj, ##__VA_ARGS__); \
794794
} \
795795
} while (0)
796+
#define CF_SWIFT_FUNCDISPATCHV(type, ret, obj, fn, ...) CF_SWIFT_FUNCDISPATCHV_CHECK(CF_IS_SWIFT, type, ret, obj, fn, ## __VA_ARGS__)
796797

797798
#define CF_SWIFT_CALLV(obj, fn, ...) __CFSwiftBridge.fn((CFSwiftRef)obj, ##__VA_ARGS__)
798799
#else

CoreFoundation/Base.subproj/ForFoundationOnly.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,9 @@ CF_EXPORT void *_CFCreateArrayStorage(size_t numPointers, Boolean zeroed, size_t
673673
#define STATIC_CLASS_NAME_LENGTH_LOOKUP___NSCFNumber 8
674674
#define STATIC_CLASS_NAME_LOOKUP___NSCFNumber NSNumberCN
675675

676+
#define STATIC_CLASS_NAME_LENGTH_LOOKUP_NSMutableData 13
677+
#define STATIC_CLASS_NAME_LOOKUP_NSMutableData NSMutableDataCN
678+
676679
#define STATIC_CLASS_NAME_CONCAT_INNER(x,y) x ## y
677680
#define STATIC_CLASS_NAME_CONCAT(x,y) STATIC_CLASS_NAME_CONCAT_INNER(x,y)
678681

CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,6 @@ struct __CFSwiftObject {
8080

8181
typedef struct __CFSwiftObject *CFSwiftRef;
8282

83-
#define CF_IS_SWIFT(type, obj) (_CFIsSwift(type, (CFSwiftRef)obj))
84-
85-
#define CF_SWIFT_FUNCDISPATCHV(type, ret, obj, fn, ...) do { \
86-
if (CF_IS_SWIFT(type, obj)) { \
87-
return (ret)__CFSwiftBridge.fn((CFSwiftRef)obj, ##__VA_ARGS__); \
88-
} \
89-
} while (0)
90-
9183
CF_EXPORT bool _CFIsSwift(CFTypeID type, CFSwiftRef obj);
9284
CF_EXPORT void _CFDeinit(CFTypeRef cf);
9385

@@ -276,6 +268,14 @@ struct _NSNumberBridge {
276268

277269
struct _NSDataBridge {
278270
_Nonnull CFTypeRef (*_Nonnull copy)(CFTypeRef obj);
271+
CFIndex (*_Nonnull length)(CFTypeRef obj);
272+
const void *_Nullable (*_Nonnull bytes)(CFTypeRef obj);
273+
void *_Nullable (*_Nonnull mutableBytes)(CFTypeRef obj);
274+
void (*_Nonnull getBytes)(CFTypeRef obj, CFRange range, void *buffer);
275+
void (*_Nonnull setLength)(CFTypeRef obj, CFIndex newLength);
276+
void (*_Nonnull increaseLengthBy)(CFTypeRef obj, CFIndex extraLength);
277+
void (*_Nonnull appendBytes)(CFTypeRef obj, const void *bytes, CFIndex length);
278+
void (*_Nonnull replaceBytes)(CFTypeRef obj, CFRange range, const void *_Nullable newBytes, CFIndex newLength);
279279
};
280280

281281
struct _NSCalendarBridge {

CoreFoundation/Collections.subproj/CFData.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,17 @@
1515
#include "CFRuntime_Internal.h"
1616
#include <string.h>
1717

18+
#if DEPLOYMENT_RUNTIME_SWIFT
19+
20+
DECLARE_STATIC_CLASS_REF(NSMutableData);
21+
static const void *_NSMutableData = STATIC_CLASS_REF(NSMutableData);
22+
static Boolean _CFDataShouldBridgeToSwift(CFTypeID type, CFDataRef data);
23+
24+
#define CF_SWIFT_NSDATA_FUNCDISPATCHV(type, ret, obj, fn, ...) CF_SWIFT_FUNCDISPATCHV_CHECK(_CFDataShouldBridgeToSwift, type, ret, obj, fn, ## __VA_ARGS__)
1825

26+
#else
27+
#define CF_SWIFT_NSDATA_FUNCDISPATCHV(...)
28+
#endif
1929

2030

2131
#if TARGET_RT_64_BIT
@@ -53,6 +63,12 @@ struct __CFData {
5363
uint8_t *_bytes; /* compaction: direct access to _bytes is only valid when data is not inline */
5464
};
5565

66+
#if DEPLOYMENT_RUNTIME_SWIFT
67+
static Boolean _CFDataShouldBridgeToSwift(CFTypeID type, CFDataRef data) {
68+
return CF_IS_SWIFT(type, data) && data->_base._cfisa != (uintptr_t)_NSMutableData;
69+
}
70+
#endif
71+
5672
/*
5773
Bit 0 = is mutable
5874
Bit 1 = growable
@@ -458,7 +474,7 @@ CFDataRef CFDataCreateCopy(CFAllocatorRef allocator, CFDataRef data) {
458474
Boolean allowRetain = true;
459475
if (allowRetain) {
460476
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), CFDataRef, (NSData *)data, copy);
461-
CF_SWIFT_FUNCDISPATCHV(CFDataGetTypeID(), CFDataRef, (CFSwiftRef)data, NSData.copy);
477+
CF_SWIFT_NSDATA_FUNCDISPATCHV(CFDataGetTypeID(), CFDataRef, (CFSwiftRef)data, NSData.copy);
462478

463479
// If the data isn't mutable...
464480
if (!__CFDataIsMutable(data)) {
@@ -499,6 +515,7 @@ CFMutableDataRef CFDataCreateMutableCopy(CFAllocatorRef allocator, CFIndex capac
499515

500516
CFIndex CFDataGetLength(CFDataRef data) {
501517
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), CFIndex, (NSData *)data, length);
518+
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, CFIndex, data, NSData.length);
502519
__CFGenericValidateType(data, CFDataGetTypeID());
503520
return __CFDataLength(data);
504521
}
@@ -510,17 +527,20 @@ CF_PRIVATE uint8_t *_CFDataGetBytePtrNonObjC(CFDataRef data) {
510527

511528
const uint8_t *CFDataGetBytePtr(CFDataRef data) {
512529
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), const uint8_t *, (NSData *)data, bytes);
530+
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, const uint8_t *, data, NSData.bytes);
513531
return _CFDataGetBytePtrNonObjC(data);
514532
}
515533

516534
uint8_t *CFDataGetMutableBytePtr(CFMutableDataRef data) {
517535
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), uint8_t *, (NSMutableData *)data, mutableBytes);
536+
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, uint8_t *, data, NSData.mutableBytes);
518537
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
519538
return _CFDataGetBytePtrNonObjC(data);
520539
}
521540

522541
void CFDataGetBytes(CFDataRef data, CFRange range, uint8_t *buffer) {
523542
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSData *)data, getBytes:(void *)buffer range:NSMakeRange(range.location, range.length));
543+
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, void, data, NSData.getBytes, range, buffer);
524544
__CFDataValidateRange(data, range, __PRETTY_FUNCTION__);
525545
memmove(buffer, _CFDataGetBytePtrNonObjC(data) + range.location, range.length);
526546
}
@@ -566,6 +586,7 @@ void CFDataSetLength(CFMutableDataRef data, CFIndex newLength) {
566586
CFIndex oldLength, capacity;
567587
Boolean isGrowable;
568588
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSMutableData *)data, setLength:(NSUInteger)newLength);
589+
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, void, data, NSData.setLength, newLength);
569590
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
570591
oldLength = __CFDataLength(data);
571592
capacity = __CFDataCapacity(data);
@@ -597,25 +618,29 @@ void CFDataSetLength(CFMutableDataRef data, CFIndex newLength) {
597618

598619
void CFDataIncreaseLength(CFMutableDataRef data, CFIndex extraLength) {
599620
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSMutableData *)data, increaseLengthBy:(NSUInteger)extraLength);
621+
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, void, data, NSData.increaseLengthBy, extraLength);
600622
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
601623
if (extraLength < 0) HALT; // Avoid integer overflow.
602624
CFDataSetLength(data, __CFDataLength(data) + extraLength);
603625
}
604626

605627
void CFDataAppendBytes(CFMutableDataRef data, const uint8_t *bytes, CFIndex length) {
606628
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSMutableData *)data, appendBytes:(const void *)bytes length:(NSUInteger)length);
629+
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, void, data, NSData.appendBytes, bytes, length);
607630
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
608631
CFDataReplaceBytes(data, CFRangeMake(__CFDataLength(data), 0), bytes, length);
609632
}
610633

611634
void CFDataDeleteBytes(CFMutableDataRef data, CFRange range) {
612635
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSMutableData *)data, replaceBytesInRange:NSMakeRange(range.location, range.length) withBytes:NULL length:0);
636+
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, void, data, NSData.replaceBytes, range, NULL, 0);
613637
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
614638
CFDataReplaceBytes(data, range, NULL, 0);
615639
}
616640

617641
void CFDataReplaceBytes(CFMutableDataRef data, CFRange range, const uint8_t *newBytes, CFIndex newLength) {
618642
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSMutableData *)data, replaceBytesInRange:NSMakeRange(range.location, range.length) withBytes:(const void *)newBytes length:(NSUInteger)newLength);
643+
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, void, data, NSData.replaceBytes, range, newBytes, newLength);
619644
__CFGenericValidateType(data, CFDataGetTypeID());
620645
__CFDataValidateRange(data, range, __PRETTY_FUNCTION__);
621646
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);

Foundation/NSData.swift

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1011,6 +1011,38 @@ extension NSData : _StructTypeBridgeable {
10111011
}
10121012
}
10131013

1014-
internal func _CFSwiftDataCreateCopy(_ data: AnyObject) -> Unmanaged<AnyObject> {
1014+
internal func _CFSwiftDataCreateCopy(_ data: CFTypeRef) -> Unmanaged<AnyObject> {
10151015
return Unmanaged<AnyObject>.passRetained((data as! NSData).copy() as! NSObject)
10161016
}
1017+
1018+
internal func _CFSwiftDataGetLength(_ data: CFTypeRef) -> CFIndex {
1019+
return (data as! NSData).length
1020+
}
1021+
1022+
internal func _CFSwiftDataGetBytesPtr(_ data: CFTypeRef) -> UnsafeRawPointer? {
1023+
return (data as! NSData).bytes
1024+
}
1025+
1026+
internal func _CFSwiftDataGetMutableBytesPtr(_ data: CFTypeRef) -> UnsafeMutableRawPointer? {
1027+
return (data as! NSMutableData).mutableBytes
1028+
}
1029+
1030+
internal func _CFSwiftDataGetBytes(_ data: CFTypeRef, _ range: CFRange, _ buffer: UnsafeMutableRawPointer) -> Void {
1031+
(data as! NSData).getBytes(buffer, range: NSMakeRange(range.location, range.length))
1032+
}
1033+
1034+
internal func _CFSwiftDataSetLength(_ data: CFTypeRef, _ newLength: CFIndex) {
1035+
(data as! NSMutableData).length = newLength
1036+
}
1037+
1038+
internal func _CFSwiftDataIncreaseLength(_ data: CFTypeRef, _ extraLength: CFIndex) {
1039+
(data as! NSMutableData).increaseLength(by: extraLength)
1040+
}
1041+
1042+
internal func _CFSwiftDataAppendBytes(_ data: CFTypeRef, _ buffer: UnsafeRawPointer, length: CFIndex) {
1043+
(data as! NSMutableData).append(buffer, length: length)
1044+
}
1045+
1046+
internal func _CFSwiftDataReplaceBytes(_ data: CFTypeRef, _ range: CFRange, _ buffer: UnsafeRawPointer?, _ count: CFIndex) {
1047+
(data as! NSMutableData).replaceBytes(in: NSMakeRange(range.location, range.length), withBytes: buffer, length: count)
1048+
}

Foundation/NSIndexSet.swift

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,62 @@ open class NSIndexSet : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
101101

102102
public static var supportsSecureCoding: Bool { return true }
103103

104-
public required init?(coder aDecoder: NSCoder) { NSUnimplemented() }
104+
public required init?(coder aDecoder: NSCoder) {
105+
let rangesCount = aDecoder.decodeInteger(forKey: "NSRangeCount")
106+
if rangesCount == 1 {
107+
let location = aDecoder.decodeInteger(forKey: "NSLocation")
108+
let length = aDecoder.decodeInteger(forKey: "NSLength")
109+
110+
_count = length
111+
_ranges = length == 0 ? [] : [NSMakeRange(location, length)]
112+
} else if rangesCount > 1 {
113+
guard let data = aDecoder.decodeObject(of: NSData.self, forKey: "NSRangeData") else {
114+
aDecoder.failWithError(NSError(domain: NSCocoaErrorDomain, code: CocoaError.coderReadCorrupt.rawValue, userInfo: [ NSLocalizedDescriptionKey: "-[NSIndexSet initWithCoder:] decoder did not provide range data" ]))
115+
return nil
116+
}
117+
118+
let sequence = PackedUIntSequence(data: data._swiftObject)
119+
guard sequence.count == rangesCount * 2 else {
120+
aDecoder.failWithError(NSError(domain: NSCocoaErrorDomain, code: CocoaError.coderReadCorrupt.rawValue, userInfo: [ NSLocalizedDescriptionKey: "Range data did not match expected length." ]))
121+
return nil
122+
}
123+
124+
var ranges: [NSRange] = []
125+
126+
let integers = sequence.unsignedIntegers
127+
var count = 0
128+
var i = 0
129+
while i <= integers.count - 2 {
130+
let range = NSRange(location: Int(integers[i]), length: Int(integers[i + 1]))
131+
count += range.length
132+
ranges.append(range)
133+
i += 2
134+
}
135+
136+
_count = count
137+
_ranges = ranges
138+
} else {
139+
_count = 0
140+
_ranges = []
141+
}
142+
}
143+
105144
open func encode(with aCoder: NSCoder) {
106-
NSUnimplemented()
145+
let rangesCount = _ranges.count
146+
147+
aCoder.encode(rangesCount, forKey: "NSRangeCount")
148+
if rangesCount == 1 {
149+
let range = _ranges[0]
150+
aCoder.encode(range.location, forKey: "NSLocation")
151+
aCoder.encode(range.length, forKey: "NSLength")
152+
} else {
153+
var sequence = PackedUIntSequence(data: Data(capacity: rangesCount * 2 + 16))
154+
for range in _ranges {
155+
sequence.append(UInt(range.location))
156+
sequence.append(UInt(range.length))
157+
}
158+
aCoder.encode(sequence.data._nsObject.copy(), forKey: "NSRangeData")
159+
}
107160
}
108161

109162
public convenience init(index value: Int) {
@@ -129,6 +182,11 @@ open class NSIndexSet : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
129182
return true
130183
}
131184

185+
open override func isEqual(_ object: Any?) -> Bool {
186+
guard let indexSet = object as? NSIndexSet else { return false }
187+
return isEqual(to: indexSet._swiftObject)
188+
}
189+
132190
open var count: Int {
133191
return _count
134192
}
@@ -788,10 +846,64 @@ open class NSMutableIndexSet : NSIndexSet {
788846
}
789847
}
790848

791-
extension NSIndexSet : _StructTypeBridgeable {
849+
extension NSIndexSet : _StructTypeBridgeable, _SwiftBridgeable {
792850
public typealias _StructType = IndexSet
793851

794852
public func _bridgeToSwift() -> IndexSet {
795853
return IndexSet._unconditionallyBridgeFromObjectiveC(self)
796854
}
855+
856+
var _swiftObject: IndexSet { return _bridgeToSwift() }
857+
}
858+
859+
// MARK: NSCoding
860+
861+
extension NSIndexSet {
862+
struct PackedUIntSequence {
863+
var data: Data
864+
init(data: Data) {
865+
self.data = data
866+
}
867+
868+
var count: Int {
869+
var result = 0
870+
for byte in data {
871+
if byte < 128 {
872+
result += 1
873+
}
874+
}
875+
return result
876+
}
877+
878+
var unsignedIntegers: [UInt] {
879+
var result: [UInt] = []
880+
var index = data.startIndex
881+
while index < data.endIndex {
882+
let fromIndex = unsignedInt(atIndex: index)
883+
result.append(fromIndex.value)
884+
index = fromIndex.nextIndex
885+
}
886+
return result
887+
}
888+
889+
private func unsignedInt(atIndex index: Int) -> (value: UInt, nextIndex: Int) {
890+
var result = UInt(data[index])
891+
if result < 128 {
892+
return (value: result, nextIndex: index + 1)
893+
} else {
894+
let fromNext = unsignedInt(atIndex: index + 1)
895+
result = (result - 128) + 128 * fromNext.value
896+
return (value: result, nextIndex: fromNext.nextIndex)
897+
}
898+
}
899+
900+
mutating func append(_ value: UInt) {
901+
if value > 127 {
902+
data.append(UInt8(128 + (value % 128)))
903+
append(value / 128)
904+
} else {
905+
data.append(UInt8(value))
906+
}
907+
}
908+
}
797909
}

Foundation/NSSwiftRuntime.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,14 @@ internal func __CFInitializeSwift() {
291291
__CFSwiftBridge.NSNumber.boolValue = _CFSwiftNumberGetBoolValue
292292

293293
__CFSwiftBridge.NSData.copy = _CFSwiftDataCreateCopy
294+
__CFSwiftBridge.NSData.length = _CFSwiftDataGetLength
295+
__CFSwiftBridge.NSData.bytes = _CFSwiftDataGetBytesPtr
296+
__CFSwiftBridge.NSData.mutableBytes = _CFSwiftDataGetMutableBytesPtr
297+
__CFSwiftBridge.NSData.getBytes = _CFSwiftDataGetBytes
298+
__CFSwiftBridge.NSData.setLength = _CFSwiftDataSetLength
299+
__CFSwiftBridge.NSData.increaseLengthBy = _CFSwiftDataIncreaseLength
300+
__CFSwiftBridge.NSData.appendBytes = _CFSwiftDataAppendBytes
301+
__CFSwiftBridge.NSData.replaceBytes = _CFSwiftDataReplaceBytes
294302

295303
__CFSwiftBridge.NSCalendar.calendarIdentifier = _CFSwiftCalendarGetCalendarIdentifier
296304
__CFSwiftBridge.NSCalendar.copyLocale = _CFSwiftCalendarCopyLocale

0 commit comments

Comments
 (0)