Skip to content

Parity: NSCoding: NSIndexSet #2216

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions CoreFoundation/Base.subproj/CFInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -788,11 +788,12 @@ extern void _CFRuntimeSetInstanceTypeIDAndIsa(CFTypeRef cf, CFTypeID newTypeID);
#if DEPLOYMENT_RUNTIME_SWIFT
#define CF_IS_SWIFT(type, obj) (_CFIsSwift(type, (CFSwiftRef)obj))

#define CF_SWIFT_FUNCDISPATCHV(type, ret, obj, fn, ...) do { \
if (CF_IS_SWIFT(type, obj)) { \
#define CF_SWIFT_FUNCDISPATCHV_CHECK(check, type, ret, obj, fn, ...) do { \
if (check(type, obj)) { \
return (ret)__CFSwiftBridge.fn((CFSwiftRef)obj, ##__VA_ARGS__); \
} \
} while (0)
#define CF_SWIFT_FUNCDISPATCHV(type, ret, obj, fn, ...) CF_SWIFT_FUNCDISPATCHV_CHECK(CF_IS_SWIFT, type, ret, obj, fn, ## __VA_ARGS__)

#define CF_SWIFT_CALLV(obj, fn, ...) __CFSwiftBridge.fn((CFSwiftRef)obj, ##__VA_ARGS__)
#else
Expand Down
3 changes: 3 additions & 0 deletions CoreFoundation/Base.subproj/ForFoundationOnly.h
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,9 @@ CF_EXPORT void *_CFCreateArrayStorage(size_t numPointers, Boolean zeroed, size_t
#define STATIC_CLASS_NAME_LENGTH_LOOKUP___NSCFNumber 8
#define STATIC_CLASS_NAME_LOOKUP___NSCFNumber NSNumberCN

#define STATIC_CLASS_NAME_LENGTH_LOOKUP_NSMutableData 13
#define STATIC_CLASS_NAME_LOOKUP_NSMutableData NSMutableDataCN

#define STATIC_CLASS_NAME_CONCAT_INNER(x,y) x ## y
#define STATIC_CLASS_NAME_CONCAT(x,y) STATIC_CLASS_NAME_CONCAT_INNER(x,y)

Expand Down
16 changes: 8 additions & 8 deletions CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,6 @@ struct __CFSwiftObject {

typedef struct __CFSwiftObject *CFSwiftRef;

#define CF_IS_SWIFT(type, obj) (_CFIsSwift(type, (CFSwiftRef)obj))

#define CF_SWIFT_FUNCDISPATCHV(type, ret, obj, fn, ...) do { \
if (CF_IS_SWIFT(type, obj)) { \
return (ret)__CFSwiftBridge.fn((CFSwiftRef)obj, ##__VA_ARGS__); \
} \
} while (0)

CF_EXPORT bool _CFIsSwift(CFTypeID type, CFSwiftRef obj);
CF_EXPORT void _CFDeinit(CFTypeRef cf);

Expand Down Expand Up @@ -276,6 +268,14 @@ struct _NSNumberBridge {

struct _NSDataBridge {
_Nonnull CFTypeRef (*_Nonnull copy)(CFTypeRef obj);
CFIndex (*_Nonnull length)(CFTypeRef obj);
const void *_Nullable (*_Nonnull bytes)(CFTypeRef obj);
void *_Nullable (*_Nonnull mutableBytes)(CFTypeRef obj);
void (*_Nonnull getBytes)(CFTypeRef obj, CFRange range, void *buffer);
void (*_Nonnull setLength)(CFTypeRef obj, CFIndex newLength);
void (*_Nonnull increaseLengthBy)(CFTypeRef obj, CFIndex extraLength);
void (*_Nonnull appendBytes)(CFTypeRef obj, const void *bytes, CFIndex length);
void (*_Nonnull replaceBytes)(CFTypeRef obj, CFRange range, const void *_Nullable newBytes, CFIndex newLength);
};

struct _NSCalendarBridge {
Expand Down
27 changes: 26 additions & 1 deletion CoreFoundation/Collections.subproj/CFData.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,17 @@
#include "CFRuntime_Internal.h"
#include <string.h>

#if DEPLOYMENT_RUNTIME_SWIFT

DECLARE_STATIC_CLASS_REF(NSMutableData);
static const void *_NSMutableData = STATIC_CLASS_REF(NSMutableData);
static Boolean _CFDataShouldBridgeToSwift(CFTypeID type, CFDataRef data);

#define CF_SWIFT_NSDATA_FUNCDISPATCHV(type, ret, obj, fn, ...) CF_SWIFT_FUNCDISPATCHV_CHECK(_CFDataShouldBridgeToSwift, type, ret, obj, fn, ## __VA_ARGS__)

#else
#define CF_SWIFT_NSDATA_FUNCDISPATCHV(...)
#endif


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

#if DEPLOYMENT_RUNTIME_SWIFT
static Boolean _CFDataShouldBridgeToSwift(CFTypeID type, CFDataRef data) {
return CF_IS_SWIFT(type, data) && data->_base._cfisa != (uintptr_t)_NSMutableData;
}
#endif

/*
Bit 0 = is mutable
Bit 1 = growable
Expand Down Expand Up @@ -458,7 +474,7 @@ CFDataRef CFDataCreateCopy(CFAllocatorRef allocator, CFDataRef data) {
Boolean allowRetain = true;
if (allowRetain) {
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), CFDataRef, (NSData *)data, copy);
CF_SWIFT_FUNCDISPATCHV(CFDataGetTypeID(), CFDataRef, (CFSwiftRef)data, NSData.copy);
CF_SWIFT_NSDATA_FUNCDISPATCHV(CFDataGetTypeID(), CFDataRef, (CFSwiftRef)data, NSData.copy);

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

CFIndex CFDataGetLength(CFDataRef data) {
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), CFIndex, (NSData *)data, length);
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, CFIndex, data, NSData.length);
__CFGenericValidateType(data, CFDataGetTypeID());
return __CFDataLength(data);
}
Expand All @@ -510,17 +527,20 @@ CF_PRIVATE uint8_t *_CFDataGetBytePtrNonObjC(CFDataRef data) {

const uint8_t *CFDataGetBytePtr(CFDataRef data) {
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), const uint8_t *, (NSData *)data, bytes);
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, const uint8_t *, data, NSData.bytes);
return _CFDataGetBytePtrNonObjC(data);
}

uint8_t *CFDataGetMutableBytePtr(CFMutableDataRef data) {
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), uint8_t *, (NSMutableData *)data, mutableBytes);
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, uint8_t *, data, NSData.mutableBytes);
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
return _CFDataGetBytePtrNonObjC(data);
}

void CFDataGetBytes(CFDataRef data, CFRange range, uint8_t *buffer) {
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSData *)data, getBytes:(void *)buffer range:NSMakeRange(range.location, range.length));
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, void, data, NSData.getBytes, range, buffer);
__CFDataValidateRange(data, range, __PRETTY_FUNCTION__);
memmove(buffer, _CFDataGetBytePtrNonObjC(data) + range.location, range.length);
}
Expand Down Expand Up @@ -566,6 +586,7 @@ void CFDataSetLength(CFMutableDataRef data, CFIndex newLength) {
CFIndex oldLength, capacity;
Boolean isGrowable;
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSMutableData *)data, setLength:(NSUInteger)newLength);
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, void, data, NSData.setLength, newLength);
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
oldLength = __CFDataLength(data);
capacity = __CFDataCapacity(data);
Expand Down Expand Up @@ -597,25 +618,29 @@ void CFDataSetLength(CFMutableDataRef data, CFIndex newLength) {

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

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

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

void CFDataReplaceBytes(CFMutableDataRef data, CFRange range, const uint8_t *newBytes, CFIndex newLength) {
CF_OBJC_FUNCDISPATCHV(CFDataGetTypeID(), void, (NSMutableData *)data, replaceBytesInRange:NSMakeRange(range.location, range.length) withBytes:(const void *)newBytes length:(NSUInteger)newLength);
CF_SWIFT_NSDATA_FUNCDISPATCHV(_kCFRuntimeIDCFData, void, data, NSData.replaceBytes, range, newBytes, newLength);
__CFGenericValidateType(data, CFDataGetTypeID());
__CFDataValidateRange(data, range, __PRETTY_FUNCTION__);
CFAssert1(__CFDataIsMutable(data), __kCFLogAssertion, "%s(): data is immutable", __PRETTY_FUNCTION__);
Expand Down
117 changes: 105 additions & 12 deletions Foundation/NSData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,13 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {

/// The number of bytes contained by the data object.
open var length: Int {
requireFunnelOverridden()
return CFDataGetLength(_cfObject)
}

/// A pointer to the data object's contents.
open var bytes: UnsafeRawPointer {
requireFunnelOverridden()
guard let bytePtr = CFDataGetBytePtr(_cfObject) else {
//This could occure on empty data being encoded.
//TODO: switch with nil when signature is fixed
Expand Down Expand Up @@ -517,14 +519,29 @@ open class NSData : NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
// MARK: - Bytes
/// Copies a number of bytes from the start of the data object into a given buffer.
open func getBytes(_ buffer: UnsafeMutableRawPointer, length: Int) {
let bytePtr = buffer.bindMemory(to: UInt8.self, capacity: length)
CFDataGetBytes(_cfObject, CFRangeMake(0, length), bytePtr)
if funnelsAreAbstract {
let actualCount = Swift.min(length, self.length)
let sourceBuffer = UnsafeRawBufferPointer(start: bytes, count: actualCount)
let destinationBuffer = UnsafeMutableRawBufferPointer(start: buffer, count: actualCount)
sourceBuffer.copyBytes(to: destinationBuffer)
} else {
let bytePtr = buffer.bindMemory(to: UInt8.self, capacity: length)
CFDataGetBytes(_cfObject, CFRangeMake(0, length), bytePtr)
}
}

/// Copies a range of bytes from the data object into a given buffer.
open func getBytes(_ buffer: UnsafeMutableRawPointer, range: NSRange) {
let bytePtr = buffer.bindMemory(to: UInt8.self, capacity: range.length)
CFDataGetBytes(_cfObject, CFRangeMake(range.location, range.length), bytePtr)
if funnelsAreAbstract {
precondition(range.location >= 0 && range.length >= 0)
let actualCount = Swift.min(range.length, self.length - range.location)
let sourceBuffer = UnsafeRawBufferPointer(start: bytes.advanced(by: range.location), count: actualCount)
let destinationBuffer = UnsafeMutableRawBufferPointer(start: buffer, count: actualCount)
sourceBuffer.copyBytes(to: destinationBuffer)
} else {
let bytePtr = buffer.bindMemory(to: UInt8.self, capacity: range.length)
CFDataGetBytes(_cfObject, CFRangeMake(range.location, range.length), bytePtr)
}
}

/// Returns a new data object containing the data object's bytes that fall within the limits specified by a given range.
Expand Down Expand Up @@ -927,15 +944,18 @@ open class NSMutableData : NSData {
// MARK: - Funnel Methods
/// A pointer to the data contained by the mutable data object.
open var mutableBytes: UnsafeMutableRawPointer {
requireFunnelOverridden()
return UnsafeMutableRawPointer(CFDataGetMutableBytePtr(_cfMutableObject))
}

/// The number of bytes contained in the mutable data object.
open override var length: Int {
get {
requireFunnelOverridden()
return CFDataGetLength(_cfObject)
}
set {
requireFunnelOverridden()
CFDataSetLength(_cfMutableObject, newValue)
}
}
Expand All @@ -948,8 +968,15 @@ open class NSMutableData : NSData {
// MARK: - Mutability
/// Appends to the data object a given number of bytes from a given buffer.
open func append(_ bytes: UnsafeRawPointer, length: Int) {
let bytePtr = bytes.bindMemory(to: UInt8.self, capacity: length)
CFDataAppendBytes(_cfMutableObject, bytePtr, length)
guard length > 0 else { return }

if funnelsAreAbstract {
self.length += length
UnsafeRawBufferPointer(start: bytes, count: length).copyBytes(to: UnsafeMutableRawBufferPointer(start: mutableBytes, count: length))
} else {
let bytePtr = bytes.bindMemory(to: UInt8.self, capacity: length)
CFDataAppendBytes(_cfMutableObject, bytePtr, length)
}
}

/// Appends the content of another data object to the data object.
Expand All @@ -962,13 +989,21 @@ open class NSMutableData : NSData {

/// Increases the length of the data object by a given number of bytes.
open func increaseLength(by extraLength: Int) {
CFDataSetLength(_cfMutableObject, CFDataGetLength(_cfObject) + extraLength)
if funnelsAreAbstract {
self.length += extraLength
} else {
CFDataSetLength(_cfMutableObject, CFDataGetLength(_cfObject) + extraLength)
}
}

/// Replaces with a given set of bytes a given range within the contents of the data object.
open func replaceBytes(in range: NSRange, withBytes bytes: UnsafeRawPointer) {
let bytePtr = bytes.bindMemory(to: UInt8.self, capacity: length)
CFDataReplaceBytes(_cfMutableObject, CFRangeMake(range.location, range.length), bytePtr, length)
if funnelsAreAbstract {
replaceBytes(in: range, withBytes: bytes, length: range.length)
} else {
let bytePtr = bytes.bindMemory(to: UInt8.self, capacity: length)
CFDataReplaceBytes(_cfMutableObject, CFRangeMake(range.location, range.length), bytePtr, length)
}
}

/// Replaces with zeroes the contents of the data object in a given range.
Expand All @@ -986,8 +1021,22 @@ open class NSMutableData : NSData {

/// Replaces with a given set of bytes a given range within the contents of the data object.
open func replaceBytes(in range: NSRange, withBytes replacementBytes: UnsafeRawPointer?, length replacementLength: Int) {
let bytePtr = replacementBytes?.bindMemory(to: UInt8.self, capacity: replacementLength)
CFDataReplaceBytes(_cfMutableObject, CFRangeMake(range.location, range.length), bytePtr, replacementLength)
precondition(range.location + range.length <= self.length)
if funnelsAreAbstract {
let delta = replacementLength - range.length
if delta != 0 {
let originalLength = self.length
self.length += delta

if delta > 0 {
UnsafeRawBufferPointer(start: mutableBytes.advanced(by: range.location), count: originalLength).copyBytes(to: UnsafeMutableRawBufferPointer(start: mutableBytes.advanced(by: range.location + range.length), count: originalLength))
}
}
UnsafeRawBufferPointer(start: replacementBytes, count: replacementLength).copyBytes(to: UnsafeMutableRawBufferPointer(start: mutableBytes.advanced(by: range.location), count: replacementLength))
} else {
let bytePtr = replacementBytes?.bindMemory(to: UInt8.self, capacity: replacementLength)
CFDataReplaceBytes(_cfMutableObject, CFRangeMake(range.location, range.length), bytePtr, replacementLength)
}
}
}

Expand All @@ -1011,6 +1060,50 @@ extension NSData : _StructTypeBridgeable {
}
}

internal func _CFSwiftDataCreateCopy(_ data: AnyObject) -> Unmanaged<AnyObject> {
internal func _CFSwiftDataCreateCopy(_ data: CFTypeRef) -> Unmanaged<AnyObject> {
return Unmanaged<AnyObject>.passRetained((data as! NSData).copy() as! NSObject)
}

internal func _CFSwiftDataGetLength(_ data: CFTypeRef) -> CFIndex {
return (data as! NSData).length
}

internal func _CFSwiftDataGetBytesPtr(_ data: CFTypeRef) -> UnsafeRawPointer? {
return (data as! NSData).bytes
}

internal func _CFSwiftDataGetMutableBytesPtr(_ data: CFTypeRef) -> UnsafeMutableRawPointer? {
return (data as! NSMutableData).mutableBytes
}

internal func _CFSwiftDataGetBytes(_ data: CFTypeRef, _ range: CFRange, _ buffer: UnsafeMutableRawPointer) -> Void {
(data as! NSData).getBytes(buffer, range: NSMakeRange(range.location, range.length))
}

internal func _CFSwiftDataSetLength(_ data: CFTypeRef, _ newLength: CFIndex) {
(data as! NSMutableData).length = newLength
}

internal func _CFSwiftDataIncreaseLength(_ data: CFTypeRef, _ extraLength: CFIndex) {
(data as! NSMutableData).increaseLength(by: extraLength)
}

internal func _CFSwiftDataAppendBytes(_ data: CFTypeRef, _ buffer: UnsafeRawPointer, length: CFIndex) {
(data as! NSMutableData).append(buffer, length: length)
}

internal func _CFSwiftDataReplaceBytes(_ data: CFTypeRef, _ range: CFRange, _ buffer: UnsafeRawPointer?, _ count: CFIndex) {
(data as! NSMutableData).replaceBytes(in: NSMakeRange(range.location, range.length), withBytes: buffer, length: count)
}

extension NSData {
var funnelsAreAbstract: Bool {
return type(of: self) != NSData.self && type(of: self) != NSMutableData.self
}

func requireFunnelOverridden() {
if funnelsAreAbstract {
NSRequiresConcreteImplementation()
}
}
}
Loading