public static let empty: DispatchData = DispatchData(data: _swift_dispatch_data_empty())
-#if false /* FIXME: dragging in _TMBO (Objective-C) */
public enum Deallocator {
/// Use `free`
case free
case unmap
/// A custom deallocator
- case custom(DispatchQueue?, @convention(block) () -> Void)
-
- private var _deallocator: (DispatchQueue?, @convention(block) () -> Void) {
+ // FIXME: Want @convention(block) here to minimize the overhead of
+ // doing the conversion (once per custom enum instance instead
+ // of once per call to DispatchData.init using the enum instance).
+ // However, adding the annotation here results in Data.o containing
+ // a reference to _TMBO (opaque metadata for Builtin.UnknownObject)
+ // which is only made available on platforms with Objective-C.
+ case custom(DispatchQueue?, () -> Void)
+
+ fileprivate var _deallocator: (DispatchQueue?, @convention(block) () -> Void) {
switch self {
case .free: return (nil, _dispatch_data_destructor_free())
case .unmap: return (nil, _dispatch_data_destructor_munmap())
}
}
}
-#endif
- internal var __wrapped: dispatch_data_t
+
+ internal var __wrapped: __DispatchData
/// Initialize a `Data` with copied memory content.
///
/// - parameter bytes: A pointer to the memory. It will be copied.
- /// - parameter count: The number of bytes to copy.
+ @available(swift, deprecated: 4, message: "Use init(bytes: UnsafeRawBufferPointer) instead")
public init(bytes buffer: UnsafeBufferPointer<UInt8>) {
- __wrapped = dispatch_data_create(
- buffer.baseAddress!, buffer.count, nil, _dispatch_data_destructor_default())
+ let d = buffer.baseAddress == nil ? _swift_dispatch_data_empty()
+ : dispatch_data_create(buffer.baseAddress!, buffer.count, nil,
+ _dispatch_data_destructor_default())
+ self.init(data: d)
+ }
+
+ /// Initialize a `Data` with copied memory content.
+ ///
+ /// - parameter bytes: A pointer to the memory. It will be copied.
+ /// - parameter count: The number of bytes to copy.
+ public init(bytes buffer: UnsafeRawBufferPointer) {
+ let d = buffer.baseAddress == nil ? _swift_dispatch_data_empty()
+ : dispatch_data_create(buffer.baseAddress!, buffer.count, nil,
+ _dispatch_data_destructor_default())
+ self.init(data: d)
}
-#if false /* FIXME: dragging in _TMBO (Objective-C) */
+
/// Initialize a `Data` without copying the bytes.
///
- /// - parameter bytes: A pointer to the bytes.
- /// - parameter count: The size of the bytes.
+ /// - parameter bytes: A buffer pointer containing the data.
/// - parameter deallocator: Specifies the mechanism to free the indicated buffer.
+ @available(swift, deprecated: 4, message: "Use init(bytesNoCopy: UnsafeRawBufferPointer, deallocater: Deallocator) instead")
public init(bytesNoCopy bytes: UnsafeBufferPointer<UInt8>, deallocator: Deallocator = .free) {
let (q, b) = deallocator._deallocator
+ let d = bytes.baseAddress == nil ? _swift_dispatch_data_empty()
+ : dispatch_data_create(bytes.baseAddress!, bytes.count, q?.__wrapped, b)
+ self.init(data: d)
+ }
- __wrapped = dispatch_data_create(bytes.baseAddress!, bytes.count, q?.__wrapped, b)
+ /// Initialize a `Data` without copying the bytes.
+ ///
+ /// - parameter bytes: A pointer to the bytes.
+ /// - parameter count: The size of the bytes.
+ /// - parameter deallocator: Specifies the mechanism to free the indicated buffer.
+ public init(bytesNoCopy bytes: UnsafeRawBufferPointer, deallocator: Deallocator = .free) {
+ let (q, b) = deallocator._deallocator
+ let d = bytes.baseAddress == nil ? _swift_dispatch_data_empty()
+ : dispatch_data_create(bytes.baseAddress!, bytes.count, q?.__wrapped, b)
+ self.init(data: d)
}
-#endif
+
internal init(data: dispatch_data_t) {
- __wrapped = data
+ __wrapped = __DispatchData(data: data, owned: true)
+ }
+
+ internal init(borrowedData: dispatch_data_t) {
+ __wrapped = __DispatchData(data: borrowedData, owned: false)
}
public var count: Int {
- return CDispatch.dispatch_data_get_size(__wrapped)
+ return CDispatch.dispatch_data_get_size(__wrapped.__wrapped)
}
public func withUnsafeBytes<Result, ContentType>(
- body: @noescape (UnsafePointer<ContentType>) throws -> Result) rethrows -> Result
+ body: (UnsafePointer<ContentType>) throws -> Result) rethrows -> Result
{
- var ptr: UnsafePointer<Void>? = nil
- var size = 0;
- let data = CDispatch.dispatch_data_create_map(__wrapped, &ptr, &size)
+ var ptr: UnsafeRawPointer? = nil
+ var size = 0
+ let data = CDispatch.dispatch_data_create_map(__wrapped.__wrapped, &ptr, &size)
+ let contentPtr = ptr!.bindMemory(
+ to: ContentType.self, capacity: size / MemoryLayout<ContentType>.stride)
defer { _fixLifetime(data) }
- return try body(UnsafePointer<ContentType>(ptr!))
+ return try body(contentPtr)
}
public func enumerateBytes(
- block: @noescape (buffer: UnsafeBufferPointer<UInt8>, byteIndex: Int, stop: inout Bool) -> Void)
+ block: (_ buffer: UnsafeBufferPointer<UInt8>, _ byteIndex: Int, _ stop: inout Bool) -> Void)
{
- _swift_dispatch_data_apply(__wrapped) { (data: dispatch_data_t, offset: Int, ptr: UnsafePointer<Void>, size: Int) in
- let bp = UnsafeBufferPointer(start: UnsafePointer<UInt8>(ptr), count: size)
- var stop = false
- block(buffer: bp, byteIndex: offset, stop: &stop)
- return !stop
+ // we know that capturing block in the closure being created/passed to dispatch_data_apply
+ // does not cause block to escape because dispatch_data_apply does not allow its
+ // block argument to escape. Therefore, the usage of withoutActuallyEscaping to
+ // bypass the Swift type system is safe.
+ withoutActuallyEscaping(block) { escapableBlock in
+ _ = CDispatch.dispatch_data_apply(__wrapped.__wrapped) { (_, offset: Int, ptr: UnsafeRawPointer, size: Int) in
+ let bytePtr = ptr.bindMemory(to: UInt8.self, capacity: size)
+ let bp = UnsafeBufferPointer(start: bytePtr, count: size)
+ var stop = false
+ escapableBlock(bp, offset, &stop)
+ return !stop
+ }
}
}
///
/// - parameter bytes: A pointer to the bytes to copy in to the data.
/// - parameter count: The number of bytes to copy.
+ @available(swift, deprecated: 4, message: "Use append(_: UnsafeRawBufferPointer) instead")
public mutating func append(_ bytes: UnsafePointer<UInt8>, count: Int) {
let data = dispatch_data_create(bytes, count, nil, _dispatch_data_destructor_default())
self.append(DispatchData(data: data))
}
+ /// Append bytes to the data.
+ ///
+ /// - parameter bytes: A pointer to the bytes to copy in to the data.
+ /// - parameter count: The number of bytes to copy.
+ public mutating func append(_ bytes: UnsafeRawBufferPointer) {
+ // Nil base address does nothing.
+ guard bytes.baseAddress != nil else { return }
+ let data = dispatch_data_create(bytes.baseAddress!, bytes.count, nil, _dispatch_data_destructor_default())
+ self.append(DispatchData(data: data))
+ }
+
/// Append data to the data.
///
/// - parameter data: The data to append to this data.
public mutating func append(_ other: DispatchData) {
- let data = CDispatch.dispatch_data_create_concat(__wrapped, other.__wrapped)
- __wrapped = data
+ let data = CDispatch.dispatch_data_create_concat(__wrapped.__wrapped, other.__wrapped.__wrapped)
+ __wrapped = __DispatchData(data: data, owned: true)
}
/// Append a buffer of bytes to the data.
///
/// - parameter buffer: The buffer of bytes to append. The size is calculated from `SourceType` and `buffer.count`.
public mutating func append<SourceType>(_ buffer : UnsafeBufferPointer<SourceType>) {
- self.append(UnsafePointer(buffer.baseAddress!), count: buffer.count * sizeof(SourceType.self))
+ let count = buffer.count * MemoryLayout<SourceType>.stride;
+ buffer.baseAddress?.withMemoryRebound(to: UInt8.self, capacity: count) {
+ self.append($0, count: count)
+ }
}
- private func _copyBytesHelper(to pointer: UnsafeMutablePointer<UInt8>, from range: CountableRange<Index>) {
+ private func _copyBytesHelper(to pointer: UnsafeMutableRawPointer, from range: CountableRange<Index>) {
var copiedCount = 0
- _ = CDispatch.dispatch_data_apply(__wrapped) { (data: dispatch_data_t, offset: Int, ptr: UnsafePointer<Void>, size: Int) in
- let limit = Swift.min((range.endIndex - range.startIndex) - copiedCount, size)
- memcpy(pointer + copiedCount, ptr, limit)
- copiedCount += limit
- return copiedCount < (range.endIndex - range.startIndex)
+ if range.isEmpty { return }
+ let rangeSize = range.count
+ _ = CDispatch.dispatch_data_apply(__wrapped.__wrapped) { (data: dispatch_data_t, offset: Int, ptr: UnsafeRawPointer, size: Int) in
+ if offset >= range.endIndex { return false } // This region is after endIndex
+ let copyOffset = range.startIndex > offset ? range.startIndex - offset : 0 // offset of first byte, in this region
+ if copyOffset >= size { return true } // This region is before startIndex
+ let count = Swift.min(rangeSize - copiedCount, size - copyOffset)
+ memcpy(pointer + copiedCount, ptr + copyOffset, count)
+ copiedCount += count
+ return copiedCount < rangeSize
}
}
/// - parameter pointer: A pointer to the buffer you wish to copy the bytes into.
/// - parameter count: The number of bytes to copy.
/// - warning: This method does not verify that the contents at pointer have enough space to hold `count` bytes.
+ @available(swift, deprecated: 4, message: "Use copyBytes(to: UnsafeMutableRawBufferPointer, count: Int) instead")
public func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, count: Int) {
_copyBytesHelper(to: pointer, from: 0..<count)
}
+
+ /// Copy the contents of the data to a pointer.
+ ///
+ /// - parameter pointer: A pointer to the buffer you wish to copy the bytes into. The buffer must be large
+ /// enough to hold `count` bytes.
+ /// - parameter count: The number of bytes to copy.
+ public func copyBytes(to pointer: UnsafeMutableRawBufferPointer, count: Int) {
+ assert(count <= pointer.count, "Buffer too small to copy \(count) bytes")
+ guard pointer.baseAddress != nil else { return }
+ _copyBytesHelper(to: pointer.baseAddress!, from: 0..<count)
+ }
/// Copy a subset of the contents of the data to a pointer.
///
/// - parameter pointer: A pointer to the buffer you wish to copy the bytes into.
/// - parameter range: The range in the `Data` to copy.
/// - warning: This method does not verify that the contents at pointer have enough space to hold the required number of bytes.
+ @available(swift, deprecated: 4, message: "Use copyBytes(to: UnsafeMutableRawBufferPointer, from: CountableRange<Index>) instead")
public func copyBytes(to pointer: UnsafeMutablePointer<UInt8>, from range: CountableRange<Index>) {
_copyBytesHelper(to: pointer, from: range)
}
+ /// Copy a subset of the contents of the data to a pointer.
+ ///
+ /// - parameter pointer: A pointer to the buffer you wish to copy the bytes into. The buffer must be large
+ /// enough to hold `count` bytes.
+ /// - parameter range: The range in the `Data` to copy.
+ public func copyBytes(to pointer: UnsafeMutableRawBufferPointer, from range: CountableRange<Index>) {
+ assert(range.count <= pointer.count, "Buffer too small to copy \(range.count) bytes")
+ guard pointer.baseAddress != nil else { return }
+ _copyBytesHelper(to: pointer.baseAddress!, from: range)
+ }
+
/// Copy the contents of the data into a buffer.
///
- /// This function copies the bytes in `range` from the data into the buffer. If the count of the `range` is greater than `sizeof(DestinationType) * buffer.count` then the first N bytes will be copied into the buffer.
+ /// This function copies the bytes in `range` from the data into the buffer. If the count of the `range` is greater than `MemoryLayout<DestinationType>.stride * buffer.count` then the first N bytes will be copied into the buffer.
/// - precondition: The range must be within the bounds of the data. Otherwise `fatalError` is called.
/// - parameter buffer: A buffer to copy the data into.
/// - parameter range: A range in the data to copy into the buffer. If the range is empty, this function will return 0 without copying anything. If the range is nil, as much data as will fit into `buffer` is copied.
precondition(r.endIndex >= 0)
precondition(r.endIndex <= cnt, "The range is outside the bounds of the data")
- copyRange = r.startIndex..<(r.startIndex + Swift.min(buffer.count * sizeof(DestinationType.self), r.count))
+ copyRange = r.startIndex..<(r.startIndex + Swift.min(buffer.count * MemoryLayout<DestinationType>.stride, r.count))
} else {
- copyRange = 0..<Swift.min(buffer.count * sizeof(DestinationType.self), cnt)
+ copyRange = 0..<Swift.min(buffer.count * MemoryLayout<DestinationType>.stride, cnt)
}
guard !copyRange.isEmpty else { return 0 }
- let pointer : UnsafeMutablePointer<UInt8> = UnsafeMutablePointer<UInt8>(buffer.baseAddress!)
- _copyBytesHelper(to: pointer, from: copyRange)
+ _copyBytesHelper(to: buffer.baseAddress!, from: copyRange)
return copyRange.count
}
/// Sets or returns the byte at the specified index.
public subscript(index: Index) -> UInt8 {
var offset = 0
- let subdata = CDispatch.dispatch_data_copy_region(__wrapped, index, &offset)
+ let subdata = CDispatch.dispatch_data_copy_region(__wrapped.__wrapped, index, &offset)
- var ptr: UnsafePointer<Void>? = nil
+ var ptr: UnsafeRawPointer? = nil
var size = 0
let map = CDispatch.dispatch_data_create_map(subdata, &ptr, &size)
defer { _fixLifetime(map) }
- let pptr = UnsafePointer<UInt8>(ptr!)
- return pptr[index - offset]
+ return ptr!.load(fromByteOffset: index - offset, as: UInt8.self)
}
public subscript(bounds: Range<Int>) -> RandomAccessSlice<DispatchData> {
/// - parameter range: The range to copy.
public func subdata(in range: CountableRange<Index>) -> DispatchData {
let subrange = CDispatch.dispatch_data_create_subrange(
- __wrapped, range.startIndex, range.endIndex - range.startIndex)
+ __wrapped.__wrapped, range.startIndex, range.endIndex - range.startIndex)
return DispatchData(data: subrange)
}
public func region(location: Int) -> (data: DispatchData, offset: Int) {
var offset: Int = 0
- let data = CDispatch.dispatch_data_copy_region(__wrapped, location, &offset)
+ let data = CDispatch.dispatch_data_copy_region(__wrapped.__wrapped, location, &offset)
return (DispatchData(data: data), offset)
}
public struct DispatchDataIterator : IteratorProtocol, Sequence {
- /// Create an iterator over the given DisaptchData
+ /// Create an iterator over the given DispatchData
public init(_data: DispatchData) {
- var ptr: UnsafePointer<Void>?
+ var ptr: UnsafeRawPointer?
self._count = 0
- self._data = CDispatch.dispatch_data_create_map(_data.__wrapped, &ptr, &self._count)
- self._ptr = UnsafePointer(ptr!)
+ self._data = __DispatchData(data: CDispatch.dispatch_data_create_map(_data.__wrapped.__wrapped, &ptr, &self._count), owned: true)
+ self._ptr = ptr
self._position = _data.startIndex
+
+ // The only time we expect a 'nil' pointer is when the data is empty.
+ assert(self._ptr != nil || self._count == self._position)
}
/// Advance to the next element and return it, or `nil` if no next
/// element exists.
- ///
- /// - Precondition: No preceding call to `self.next()` has returned `nil`.
public mutating func next() -> DispatchData._Element? {
if _position == _count { return nil }
- let element = _ptr[_position];
+ let element = _ptr.load(fromByteOffset: _position, as: UInt8.self)
_position = _position + 1
return element
}
- internal let _data: dispatch_data_t
- internal var _ptr: UnsafePointer<UInt8>
+ internal let _data: __DispatchData
+ internal var _ptr: UnsafeRawPointer!
internal var _count: Int
internal var _position: DispatchData.Index
}
-typealias _swift_data_applier = @convention(block) @noescape (dispatch_data_t, Int, UnsafePointer<Void>, Int) -> Bool
-
-@_silgen_name("_swift_dispatch_data_apply")
-internal func _swift_dispatch_data_apply(_ data: dispatch_data_t, _ block: _swift_data_applier)
-
@_silgen_name("_swift_dispatch_data_empty")
internal func _swift_dispatch_data_empty() -> dispatch_data_t