mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
To send them across actors, they need to be wrapped in an '@unchecked Sendable' type. Typically such a wrapper type would be be responsible for ensuring its uniqueness or immutability. Inferring Sendability for arbitrary types that contain Unsafe*Pointers would introduce race conditions without warning or any explicit acknoledgement from the programmer that the pointer is in fact unique.
755 lines
28 KiB
Swift
755 lines
28 KiB
Swift
//===--- UnsafeBufferPointer.swift.gyb ------------------------*- swift -*-===//
|
||
//
|
||
// This source file is part of the Swift.org open source project
|
||
//
|
||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||
//
|
||
// See https://swift.org/LICENSE.txt for license information
|
||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||
//
|
||
//===----------------------------------------------------------------------===//
|
||
|
||
|
||
% for mutable in (True, False):
|
||
% Self = 'UnsafeMutableBufferPointer' if mutable else 'UnsafeBufferPointer'
|
||
% Mutable = 'Mutable' if mutable else ''
|
||
/// A nonowning collection interface to a buffer of ${Mutable.lower()}
|
||
/// elements stored contiguously in memory.
|
||
///
|
||
/// You can use an `${Self}` instance in low level operations to eliminate
|
||
/// uniqueness checks and, in release mode, bounds checks. Bounds checks are
|
||
/// always performed in debug mode.
|
||
///
|
||
/// ${Self} Semantics
|
||
/// =================
|
||
///
|
||
/// An `${Self}` instance is a view into memory and does not own the memory
|
||
/// that it references. Copying a value of type `${Self}` does not copy the
|
||
/// instances stored in the underlying memory. However, initializing another
|
||
/// collection with an `${Self}` instance copies the instances out of the
|
||
/// referenced memory and into the new collection.
|
||
// FIXME: rdar://18157434 - until this is fixed, this has to be fixed layout
|
||
// to avoid a hang in Foundation, which has the following setup:
|
||
// struct A { struct B { let x: UnsafeMutableBufferPointer<...> } let b: B }
|
||
@frozen // unsafe-performance
|
||
public struct Unsafe${Mutable}BufferPointer<Element> {
|
||
|
||
@usableFromInline
|
||
let _position: Unsafe${Mutable}Pointer<Element>?
|
||
|
||
/// The number of elements in the buffer.
|
||
///
|
||
/// If the `baseAddress` of this buffer is `nil`, the count is zero. However,
|
||
/// a buffer can have a `count` of zero even with a non-`nil` base address.
|
||
public let count: Int
|
||
|
||
// This works around _debugPrecondition() impacting the performance of
|
||
// optimized code. (rdar://72246338)
|
||
@_alwaysEmitIntoClient
|
||
internal init(
|
||
@_nonEphemeral _uncheckedStart start: Unsafe${Mutable}Pointer<Element>?,
|
||
count: Int
|
||
) {
|
||
_position = start
|
||
self.count = count
|
||
}
|
||
|
||
/// Creates a new buffer pointer over the specified number of contiguous
|
||
/// instances beginning at the given pointer.
|
||
///
|
||
/// - Parameters:
|
||
/// - start: A pointer to the start of the buffer, or `nil`. If `start` is
|
||
/// `nil`, `count` must be zero. However, `count` may be zero even for a
|
||
/// non-`nil` `start`. The pointer passed as `start` must be aligned to
|
||
/// `MemoryLayout<Element>.alignment`.
|
||
/// - count: The number of instances in the buffer. `count` must not be
|
||
/// negative.
|
||
@inlinable // unsafe-performance
|
||
public init(
|
||
@_nonEphemeral start: Unsafe${Mutable}Pointer<Element>?, count: Int
|
||
) {
|
||
_debugPrecondition(
|
||
count >= 0, "Unsafe${Mutable}BufferPointer with negative count")
|
||
_debugPrecondition(
|
||
count == 0 || start != nil,
|
||
"Unsafe${Mutable}BufferPointer has a nil start and nonzero count")
|
||
self.init(_uncheckedStart: start, count: _assumeNonNegative(count))
|
||
}
|
||
|
||
@inlinable // unsafe-performance
|
||
public init(_empty: ()) {
|
||
_position = nil
|
||
count = 0
|
||
}
|
||
|
||
% if Mutable:
|
||
|
||
/// Creates a mutable typed buffer pointer referencing the same memory as the
|
||
/// given immutable buffer pointer.
|
||
///
|
||
/// - Parameter other: The immutable buffer pointer to convert.
|
||
@inlinable // unsafe-performance
|
||
public init(mutating other: UnsafeBufferPointer<Element>) {
|
||
_position = UnsafeMutablePointer<Element>(mutating: other._position)
|
||
count = other.count
|
||
}
|
||
% else:
|
||
/// Creates an immutable typed buffer pointer referencing the same memory as the
|
||
/// given mutable buffer pointer.
|
||
///
|
||
/// - Parameter other: The mutable buffer pointer to convert.
|
||
@inlinable // unsafe-performance
|
||
public init(_ other: UnsafeMutableBufferPointer<Element>) {
|
||
_position = UnsafePointer<Element>(other._position)
|
||
count = other.count
|
||
}
|
||
% end
|
||
}
|
||
|
||
%if not mutable:
|
||
extension UnsafeBufferPointer {
|
||
/// An iterator for the elements in the buffer referenced by an
|
||
/// `UnsafeBufferPointer` or `UnsafeMutableBufferPointer` instance.
|
||
@frozen // unsafe-performance
|
||
public struct Iterator {
|
||
@usableFromInline
|
||
internal var _position, _end: UnsafePointer<Element>?
|
||
|
||
@inlinable // unsafe-performance
|
||
public init(_position: UnsafePointer<Element>?, _end: UnsafePointer<Element>?) {
|
||
self._position = _position
|
||
self._end = _end
|
||
}
|
||
}
|
||
}
|
||
|
||
extension UnsafeBufferPointer.Iterator: IteratorProtocol {
|
||
/// Advances to the next element and returns it, or `nil` if no next element
|
||
/// exists.
|
||
///
|
||
/// Once `nil` has been returned, all subsequent calls return `nil`.
|
||
@inlinable // unsafe-performance
|
||
public mutating func next() -> Element? {
|
||
guard let start = _position else {
|
||
return nil
|
||
}
|
||
_internalInvariant(_end != nil, "inconsistent _position, _end pointers")
|
||
|
||
if start == _end._unsafelyUnwrappedUnchecked { return nil }
|
||
|
||
let result = start.pointee
|
||
_position = start + 1
|
||
return result
|
||
}
|
||
}
|
||
%else:
|
||
extension UnsafeMutableBufferPointer {
|
||
public typealias Iterator = UnsafeBufferPointer<Element>.Iterator
|
||
}
|
||
%end
|
||
|
||
extension Unsafe${Mutable}BufferPointer: Sequence {
|
||
/// Returns an iterator over the elements of this buffer.
|
||
///
|
||
/// - Returns: An iterator over the elements of this buffer.
|
||
@inlinable // unsafe-performance
|
||
public func makeIterator() -> Iterator {
|
||
guard let start = _position else {
|
||
return Iterator(_position: nil, _end: nil)
|
||
}
|
||
return Iterator(_position: start, _end: start + count)
|
||
}
|
||
|
||
/// Initializes the memory at `destination.baseAddress` with elements of `self`,
|
||
/// stopping when either `self` or `destination` is exhausted.
|
||
///
|
||
/// - Returns: an iterator over any remaining elements of `self` and the
|
||
/// number of elements initialized.
|
||
@inlinable // unsafe-performance
|
||
public func _copyContents(
|
||
initializing destination: UnsafeMutableBufferPointer<Element>
|
||
) -> (Iterator, UnsafeMutableBufferPointer<Element>.Index) {
|
||
guard !isEmpty && !destination.isEmpty else { return (makeIterator(), 0) }
|
||
let s = self.baseAddress._unsafelyUnwrappedUnchecked
|
||
let d = destination.baseAddress._unsafelyUnwrappedUnchecked
|
||
let n = Swift.min(destination.count, self.count)
|
||
d.initialize(from: s, count: n)
|
||
return (Iterator(_position: s + n, _end: s + count), n)
|
||
}
|
||
}
|
||
|
||
extension Unsafe${Mutable}BufferPointer: ${Mutable}Collection, RandomAccessCollection {
|
||
public typealias Index = Int
|
||
public typealias Indices = Range<Int>
|
||
|
||
/// The index of the first element in a nonempty buffer.
|
||
///
|
||
/// The `startIndex` property of an `Unsafe${Mutable}BufferPointer` instance
|
||
/// is always zero.
|
||
@inlinable // unsafe-performance
|
||
public var startIndex: Int { return 0 }
|
||
|
||
/// The "past the end" position---that is, the position one greater than the
|
||
/// last valid subscript argument.
|
||
///
|
||
/// The `endIndex` property of an `Unsafe${Mutable}BufferPointer` instance is
|
||
/// always identical to `count`.
|
||
@inlinable // unsafe-performance
|
||
public var endIndex: Int { return count }
|
||
|
||
@inlinable // unsafe-performance
|
||
public func index(after i: Int) -> Int {
|
||
// NOTE: this is a manual specialization of index movement for a Strideable
|
||
// index that is required for UnsafeBufferPointer performance. The
|
||
// optimizer is not capable of creating partial specializations yet.
|
||
// NOTE: Range checks are not performed here, because it is done later by
|
||
// the subscript function.
|
||
return i + 1
|
||
}
|
||
|
||
@inlinable // unsafe-performance
|
||
public func formIndex(after i: inout Int) {
|
||
// NOTE: this is a manual specialization of index movement for a Strideable
|
||
// index that is required for UnsafeBufferPointer performance. The
|
||
// optimizer is not capable of creating partial specializations yet.
|
||
// NOTE: Range checks are not performed here, because it is done later by
|
||
// the subscript function.
|
||
i += 1
|
||
}
|
||
|
||
@inlinable // unsafe-performance
|
||
public func index(before i: Int) -> Int {
|
||
// NOTE: this is a manual specialization of index movement for a Strideable
|
||
// index that is required for UnsafeBufferPointer performance. The
|
||
// optimizer is not capable of creating partial specializations yet.
|
||
// NOTE: Range checks are not performed here, because it is done later by
|
||
// the subscript function.
|
||
return i - 1
|
||
}
|
||
|
||
@inlinable // unsafe-performance
|
||
public func formIndex(before i: inout Int) {
|
||
// NOTE: this is a manual specialization of index movement for a Strideable
|
||
// index that is required for UnsafeBufferPointer performance. The
|
||
// optimizer is not capable of creating partial specializations yet.
|
||
// NOTE: Range checks are not performed here, because it is done later by
|
||
// the subscript function.
|
||
i -= 1
|
||
}
|
||
|
||
@inlinable // unsafe-performance
|
||
public func index(_ i: Int, offsetBy n: Int) -> Int {
|
||
// NOTE: this is a manual specialization of index movement for a Strideable
|
||
// index that is required for UnsafeBufferPointer performance. The
|
||
// optimizer is not capable of creating partial specializations yet.
|
||
// NOTE: Range checks are not performed here, because it is done later by
|
||
// the subscript function.
|
||
return i + n
|
||
}
|
||
|
||
@inlinable // unsafe-performance
|
||
public func index(_ i: Int, offsetBy n: Int, limitedBy limit: Int) -> Int? {
|
||
// NOTE: this is a manual specialization of index movement for a Strideable
|
||
// index that is required for UnsafeBufferPointer performance. The
|
||
// optimizer is not capable of creating partial specializations yet.
|
||
// NOTE: Range checks are not performed here, because it is done later by
|
||
// the subscript function.
|
||
let l = limit - i
|
||
if n > 0 ? l >= 0 && l < n : l <= 0 && n < l {
|
||
return nil
|
||
}
|
||
return i + n
|
||
}
|
||
|
||
@inlinable // unsafe-performance
|
||
public func distance(from start: Int, to end: Int) -> Int {
|
||
// NOTE: this is a manual specialization of index movement for a Strideable
|
||
// index that is required for UnsafeBufferPointer performance. The
|
||
// optimizer is not capable of creating partial specializations yet.
|
||
// NOTE: Range checks are not performed here, because it is done later by
|
||
// the subscript function.
|
||
// NOTE: We allow the subtraction to silently overflow in release builds
|
||
// to eliminate a superflous check when `start` and `end` are both valid
|
||
// indices. (The operation can only overflow if `start` is negative, which
|
||
// implies it's an invalid index.) `Collection` does not specify what
|
||
// `distance` should return when given an invalid index pair.
|
||
let result = end.subtractingReportingOverflow(start)
|
||
_debugPrecondition(!result.overflow)
|
||
return result.partialValue
|
||
}
|
||
|
||
@inlinable // unsafe-performance
|
||
public func _failEarlyRangeCheck(_ index: Int, bounds: Range<Int>) {
|
||
// NOTE: In release mode, this method is a no-op for performance reasons.
|
||
_debugPrecondition(index >= bounds.lowerBound)
|
||
_debugPrecondition(index < bounds.upperBound)
|
||
}
|
||
|
||
@inlinable // unsafe-performance
|
||
public func _failEarlyRangeCheck(_ range: Range<Int>, bounds: Range<Int>) {
|
||
// NOTE: In release mode, this method is a no-op for performance reasons.
|
||
_debugPrecondition(range.lowerBound >= bounds.lowerBound)
|
||
_debugPrecondition(range.upperBound <= bounds.upperBound)
|
||
}
|
||
|
||
@inlinable // unsafe-performance
|
||
public var indices: Indices {
|
||
return startIndex..<endIndex
|
||
}
|
||
|
||
/// Accesses the element at the specified position.
|
||
///
|
||
%if Mutable:
|
||
/// The following example uses the buffer pointer's subscript to access and
|
||
/// modify the elements of a mutable buffer pointing to the contiguous
|
||
/// contents of an array:
|
||
///
|
||
/// var numbers = [1, 2, 3, 4, 5]
|
||
/// numbers.withUnsafeMutableBufferPointer { buffer in
|
||
/// for i in stride(from: buffer.startIndex, to: buffer.endIndex - 1, by: 2) {
|
||
/// let x = buffer[i]
|
||
/// buffer[i + 1] = buffer[i]
|
||
/// buffer[i] = x
|
||
/// }
|
||
/// }
|
||
/// print(numbers)
|
||
/// // Prints "[2, 1, 4, 3, 5]"
|
||
%else:
|
||
/// The following example uses the buffer pointer's subscript to access every
|
||
/// other element of the buffer:
|
||
///
|
||
/// let numbers = [1, 2, 3, 4, 5]
|
||
/// let sum = numbers.withUnsafeBufferPointer { buffer -> Int in
|
||
/// var result = 0
|
||
/// for i in stride(from: buffer.startIndex, to: buffer.endIndex, by: 2) {
|
||
/// result += buffer[i]
|
||
/// }
|
||
/// return result
|
||
/// }
|
||
/// // 'sum' == 9
|
||
%end
|
||
///
|
||
/// - Note: Bounds checks for `i` are performed only in debug mode.
|
||
///
|
||
/// - Parameter i: The position of the element to access. `i` must be in the
|
||
/// range `0..<count`.
|
||
@inlinable // unsafe-performance
|
||
public subscript(i: Int) -> Element {
|
||
get {
|
||
_debugPrecondition(i >= 0)
|
||
_debugPrecondition(i < endIndex)
|
||
return _position._unsafelyUnwrappedUnchecked[i]
|
||
}
|
||
%if Mutable:
|
||
nonmutating _modify {
|
||
_debugPrecondition(i >= 0)
|
||
_debugPrecondition(i < endIndex)
|
||
yield &_position._unsafelyUnwrappedUnchecked[i]
|
||
}
|
||
%end
|
||
}
|
||
|
||
// Skip all debug and runtime checks
|
||
|
||
@inlinable // unsafe-performance
|
||
internal subscript(_unchecked i: Int) -> Element {
|
||
get {
|
||
_internalInvariant(i >= 0)
|
||
_internalInvariant(i < endIndex)
|
||
return _position._unsafelyUnwrappedUnchecked[i]
|
||
}
|
||
%if Mutable:
|
||
nonmutating _modify {
|
||
_internalInvariant(i >= 0)
|
||
_internalInvariant(i < endIndex)
|
||
yield &_position._unsafelyUnwrappedUnchecked[i]
|
||
}
|
||
%end
|
||
}
|
||
|
||
/// Accesses a contiguous subrange of the buffer's elements.
|
||
///
|
||
/// The accessed slice uses the same indices for the same elements as the
|
||
/// original buffer uses. Always use the slice's `startIndex` property
|
||
/// instead of assuming that its indices start at a particular value.
|
||
///
|
||
/// This example demonstrates getting a slice from a buffer of strings, finding
|
||
/// the index of one of the strings in the slice, and then using that index
|
||
/// in the original buffer.
|
||
///
|
||
%if Mutable:
|
||
/// var streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"]
|
||
/// streets.withUnsafeMutableBufferPointer { buffer in
|
||
/// let streetSlice = buffer[2..<buffer.endIndex]
|
||
/// print(Array(streetSlice))
|
||
/// // Prints "["Channing", "Douglas", "Evarts"]"
|
||
/// let index = streetSlice.firstIndex(of: "Evarts") // 4
|
||
/// buffer[index!] = "Eustace"
|
||
/// }
|
||
/// print(streets.last!)
|
||
/// // Prints "Eustace"
|
||
%else:
|
||
/// let streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"]
|
||
/// streets.withUnsafeBufferPointer { buffer in
|
||
/// let streetSlice = buffer[2..<buffer.endIndex]
|
||
/// print(Array(streetSlice))
|
||
/// // Prints "["Channing", "Douglas", "Evarts"]"
|
||
/// let index = streetSlice.firstIndex(of: "Evarts") // 4
|
||
/// print(buffer[index!])
|
||
/// // Prints "Evarts"
|
||
/// }
|
||
%end
|
||
///
|
||
/// - Note: Bounds checks for `bounds` are performed only in debug mode.
|
||
///
|
||
/// - Parameter bounds: A range of the buffer's indices. The bounds of
|
||
/// the range must be valid indices of the buffer.
|
||
@inlinable // unsafe-performance
|
||
public subscript(bounds: Range<Int>)
|
||
-> Slice<Unsafe${Mutable}BufferPointer<Element>>
|
||
{
|
||
get {
|
||
_debugPrecondition(bounds.lowerBound >= startIndex)
|
||
_debugPrecondition(bounds.upperBound <= endIndex)
|
||
return Slice(
|
||
base: self, bounds: bounds)
|
||
}
|
||
% if Mutable:
|
||
nonmutating set {
|
||
_debugPrecondition(bounds.lowerBound >= startIndex)
|
||
_debugPrecondition(bounds.upperBound <= endIndex)
|
||
_debugPrecondition(bounds.count == newValue.count)
|
||
|
||
// FIXME: swift-3-indexing-model: tests.
|
||
if !newValue.isEmpty {
|
||
(_position! + bounds.lowerBound).assign(
|
||
from: newValue.base._position! + newValue.startIndex,
|
||
count: newValue.count)
|
||
}
|
||
}
|
||
% end
|
||
}
|
||
% if mutable:
|
||
|
||
/// Exchanges the values at the specified indices of the buffer.
|
||
///
|
||
/// Both parameters must be valid indices of the buffer, and not
|
||
/// equal to `endIndex`. Passing the same index as both `i` and `j` has no
|
||
/// effect.
|
||
///
|
||
/// - Parameters:
|
||
/// - i: The index of the first value to swap.
|
||
/// - j: The index of the second value to swap.
|
||
@inlinable // unsafe-performance
|
||
public func swapAt(_ i: Int, _ j: Int) {
|
||
guard i != j else { return }
|
||
_debugPrecondition(i >= 0 && j >= 0)
|
||
_debugPrecondition(i < endIndex && j < endIndex)
|
||
let pi = (_position! + i)
|
||
let pj = (_position! + j)
|
||
let tmp = pi.move()
|
||
pi.moveInitialize(from: pj, count: 1)
|
||
pj.initialize(to: tmp)
|
||
}
|
||
% end # mutable
|
||
}
|
||
|
||
extension Unsafe${Mutable}BufferPointer {
|
||
% if Mutable:
|
||
@inlinable
|
||
@available(*, deprecated, renamed: "withContiguousMutableStorageIfAvailable")
|
||
public mutating func _withUnsafeMutableBufferPointerIfSupported<R>(
|
||
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
|
||
) rethrows -> R? {
|
||
return try body(&self)
|
||
}
|
||
|
||
@inlinable
|
||
public mutating func withContiguousMutableStorageIfAvailable<R>(
|
||
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
|
||
) rethrows -> R? {
|
||
let (oldBase, oldCount) = (self.baseAddress, self.count)
|
||
defer {
|
||
_debugPrecondition((oldBase, oldCount) == (self.baseAddress, self.count),
|
||
"UnsafeMutableBufferPointer.withContiguousMutableStorageIfAvailable: replacing the buffer is not allowed")
|
||
}
|
||
return try body(&self)
|
||
}
|
||
|
||
@inlinable
|
||
public func withContiguousStorageIfAvailable<R>(
|
||
_ body: (UnsafeBufferPointer<Element>) throws -> R
|
||
) rethrows -> R? {
|
||
return try body(UnsafeBufferPointer(self))
|
||
}
|
||
|
||
% else:
|
||
|
||
@inlinable
|
||
public func withContiguousStorageIfAvailable<R>(
|
||
_ body: (UnsafeBufferPointer<Element>) throws -> R
|
||
) rethrows -> R? {
|
||
return try body(self)
|
||
}
|
||
|
||
% end
|
||
|
||
% if not Mutable:
|
||
|
||
/// Creates a buffer over the same memory as the given buffer slice.
|
||
///
|
||
/// The new buffer represents the same region of memory as `slice`, but is
|
||
/// indexed starting at zero instead of sharing indices with the original
|
||
/// buffer. For example:
|
||
///
|
||
/// let buffer = returnsABuffer()
|
||
/// let n = 5
|
||
/// let slice = buffer[n...]
|
||
/// let rebased = UnsafeBufferPointer(rebasing: slice)
|
||
///
|
||
/// After rebasing `slice` as the `rebased` buffer, the following are true:
|
||
///
|
||
/// - `rebased.startIndex == 0`
|
||
/// - `rebased[0] == slice[n]`
|
||
/// - `rebased[0] == buffer[n]`
|
||
/// - `rebased.count == slice.count`
|
||
///
|
||
/// - Parameter slice: The buffer slice to rebase.
|
||
@inlinable // unsafe-performance
|
||
public init(rebasing slice: Slice<UnsafeBufferPointer<Element>>) {
|
||
// NOTE: `Slice` does not guarantee that its start/end indices are valid
|
||
// in `base` -- it merely ensures that `startIndex <= endIndex`.
|
||
// We need manually check that we aren't given an invalid slice,
|
||
// or the resulting collection would allow access that was
|
||
// out-of-bounds with respect to the original base buffer.
|
||
// We only do this in debug builds to prevent a measurable performance
|
||
// degradation wrt passing around pointers not wrapped in a BufferPointer
|
||
// construct.
|
||
_debugPrecondition(
|
||
slice.startIndex >= 0 && slice.endIndex <= slice.base.count,
|
||
"Invalid slice")
|
||
let base = slice.base.baseAddress?.advanced(by: slice.startIndex)
|
||
let count = slice.endIndex &- slice.startIndex
|
||
self.init(start: base, count: count)
|
||
}
|
||
|
||
% end
|
||
|
||
/// Creates a buffer over the same memory as the given buffer slice.
|
||
///
|
||
/// The new buffer represents the same region of memory as `slice`, but is
|
||
/// indexed starting at zero instead of sharing indices with the original
|
||
/// buffer. For example:
|
||
///
|
||
/// let buffer = returnsABuffer()
|
||
/// let n = 5
|
||
/// let slice = buffer[n...]
|
||
/// let rebased = Unsafe${Mutable}BufferPointer(rebasing: slice)
|
||
///
|
||
/// After rebasing `slice` as the `rebased` buffer, the following are true:
|
||
///
|
||
/// - `rebased.startIndex == 0`
|
||
/// - `rebased[0] == slice[n]`
|
||
/// - `rebased[0] == buffer[n]`
|
||
/// - `rebased.count == slice.count`
|
||
///
|
||
/// - Parameter slice: The buffer slice to rebase.
|
||
@inlinable // unsafe-performance
|
||
public init(rebasing slice: Slice<UnsafeMutableBufferPointer<Element>>) {
|
||
let base = slice.base.baseAddress?.advanced(by: slice.startIndex)
|
||
let count = slice.endIndex &- slice.startIndex
|
||
self.init(start: base, count: count)
|
||
}
|
||
|
||
/// Deallocates the memory block previously allocated at this buffer pointer’s
|
||
/// base address.
|
||
///
|
||
/// This buffer pointer's `baseAddress` must be `nil` or a pointer to a memory
|
||
/// block previously returned by a Swift allocation method. If `baseAddress` is
|
||
/// `nil`, this function does nothing. Otherwise, the memory must not be initialized
|
||
/// or `Pointee` must be a trivial type. This buffer pointer's `count` must
|
||
/// be equal to the originally allocated size of the memory block.
|
||
@inlinable // unsafe-performance
|
||
public func deallocate() {
|
||
_position?.deallocate()
|
||
}
|
||
|
||
% if Mutable:
|
||
|
||
/// Allocates uninitialized memory for the specified number of instances of
|
||
/// type `Element`.
|
||
///
|
||
/// The resulting buffer references a region of memory that is bound to
|
||
/// `Element` and is `count * MemoryLayout<Element>.stride` bytes in size.
|
||
///
|
||
/// The following example allocates a buffer that can store four `Int`
|
||
/// instances and then initializes that memory with the elements of a range:
|
||
///
|
||
/// let buffer = UnsafeMutableBufferPointer<Int>.allocate(capacity: 4)
|
||
/// _ = buffer.initialize(from: 1...4)
|
||
/// print(buffer[2])
|
||
/// // Prints "3"
|
||
///
|
||
/// When you allocate memory, always remember to deallocate once you're
|
||
/// finished.
|
||
///
|
||
/// buffer.deallocate()
|
||
///
|
||
/// - Parameter count: The amount of memory to allocate, counted in instances
|
||
/// of `Element`.
|
||
@inlinable // unsafe-performance
|
||
public static func allocate(capacity count: Int)
|
||
-> UnsafeMutableBufferPointer<Element> {
|
||
let base = UnsafeMutablePointer<Element>.allocate(capacity: count)
|
||
return UnsafeMutableBufferPointer(start: base, count: count)
|
||
}
|
||
|
||
/// Initializes every element in this buffer's memory to a copy of the given value.
|
||
///
|
||
/// The destination memory must be uninitialized or the buffer's `Element`
|
||
/// must be a trivial type. After a call to `initialize(repeating:)`, the
|
||
/// entire region of memory referenced by this buffer is initialized.
|
||
///
|
||
/// - Parameters:
|
||
/// - repeatedValue: The instance to initialize this buffer's memory with.
|
||
@inlinable // unsafe-performance
|
||
public func initialize(repeating repeatedValue: Element) {
|
||
guard let dstBase = _position else {
|
||
return
|
||
}
|
||
|
||
dstBase.initialize(repeating: repeatedValue, count: count)
|
||
}
|
||
|
||
/// Assigns every element in this buffer's memory to a copy of the given value.
|
||
///
|
||
/// The buffer’s memory must be initialized or the buffer's `Element`
|
||
/// must be a trivial type.
|
||
///
|
||
/// - Parameters:
|
||
/// - repeatedValue: The instance to assign this buffer's memory to.
|
||
///
|
||
/// Warning: All buffer elements must be initialized before calling this.
|
||
/// Assigning to part of the buffer must be done using the `assign(repeating:count:)`
|
||
/// method on the buffer’s `baseAddress`.
|
||
@inlinable // unsafe-performance
|
||
public func assign(repeating repeatedValue: Element) {
|
||
guard let dstBase = _position else {
|
||
return
|
||
}
|
||
|
||
dstBase.assign(repeating: repeatedValue, count: count)
|
||
}
|
||
|
||
% end
|
||
|
||
/// Executes the given closure while temporarily binding the memory referenced
|
||
/// by this buffer to the given type.
|
||
///
|
||
/// Use this method when you have a buffer of memory bound to one type and
|
||
/// you need to access that memory as a buffer of another type. Accessing
|
||
/// memory as type `T` requires that the memory be bound to that type. A
|
||
/// memory location may only be bound to one type at a time, so accessing
|
||
/// the same memory as an unrelated type without first rebinding the memory
|
||
/// is undefined.
|
||
///
|
||
/// The entire region of memory referenced by this buffer must be initialized.
|
||
///
|
||
/// Because this buffer's memory is no longer bound to its `Element` type
|
||
/// while the `body` closure executes, do not access memory using the
|
||
/// original buffer from within `body`. Instead, use the `body` closure's
|
||
/// buffer argument to access the values in memory as instances of type
|
||
/// `T`.
|
||
///
|
||
/// After executing `body`, this method rebinds memory back to the original
|
||
/// `Element` type.
|
||
///
|
||
/// - Note: Only use this method to rebind the buffer's memory to a type
|
||
/// with the same size and stride as the currently bound `Element` type.
|
||
/// To bind a region of memory to a type that is a different size, convert
|
||
/// the buffer to a raw buffer and use the `bindMemory(to:)` method.
|
||
///
|
||
/// - Parameters:
|
||
/// - type: The type to temporarily bind the memory referenced by this
|
||
/// buffer. The type `T` must have the same size and be layout compatible
|
||
/// with the pointer's `Element` type.
|
||
/// - body: A closure that takes a ${Mutable.lower()} typed buffer to the
|
||
/// same memory as this buffer, only bound to type `T`. The buffer argument
|
||
/// contains the same number of complete instances of `T` as the original
|
||
/// buffer’s `count`. The closure's buffer argument is valid only for the
|
||
/// duration of the closure's execution. If `body` has a return value, that
|
||
/// value is also used as the return value for the `withMemoryRebound(to:_:)`
|
||
/// method.
|
||
/// - Returns: The return value, if any, of the `body` closure parameter.
|
||
@inlinable // unsafe-performance
|
||
public func withMemoryRebound<T, Result>(
|
||
to type: T.Type, _ body: (${Self}<T>) throws -> Result
|
||
) rethrows -> Result {
|
||
if let base = _position {
|
||
_debugPrecondition(MemoryLayout<Element>.stride == MemoryLayout<T>.stride)
|
||
Builtin.bindMemory(base._rawValue, count._builtinWordValue, T.self)
|
||
defer {
|
||
Builtin.bindMemory(base._rawValue, count._builtinWordValue, Element.self)
|
||
}
|
||
|
||
return try body(${Self}<T>(
|
||
start: Unsafe${Mutable}Pointer<T>(base._rawValue), count: count))
|
||
}
|
||
else {
|
||
return try body(${Self}<T>(start: nil, count: 0))
|
||
}
|
||
}
|
||
|
||
/// A pointer to the first element of the buffer.
|
||
///
|
||
/// If the `baseAddress` of this buffer is `nil`, the count is zero. However,
|
||
/// a buffer can have a `count` of zero even with a non-`nil` base address.
|
||
@inlinable // unsafe-performance
|
||
public var baseAddress: Unsafe${Mutable}Pointer<Element>? {
|
||
return _position
|
||
}
|
||
}
|
||
|
||
extension Unsafe${Mutable}BufferPointer: CustomDebugStringConvertible {
|
||
/// A textual representation of the buffer, suitable for debugging.
|
||
public var debugDescription: String {
|
||
return "Unsafe${Mutable}BufferPointer"
|
||
+ "(start: \(_position.map(String.init(describing:)) ?? "nil"), count: \(count))"
|
||
}
|
||
}
|
||
%end
|
||
|
||
|
||
extension UnsafeMutableBufferPointer {
|
||
/// Initializes the buffer's memory with the given elements.
|
||
///
|
||
/// When calling the `initialize(from:)` method on a buffer `b`, the memory
|
||
/// referenced by `b` must be uninitialized or the `Element` type must be a
|
||
/// trivial type. After the call, the memory referenced by this buffer up
|
||
/// to, but not including, the returned index is initialized. The buffer
|
||
/// must contain sufficient memory to accommodate
|
||
/// `source.underestimatedCount`.
|
||
///
|
||
/// The returned index is the position of the element in the buffer one past
|
||
/// the last element written. If `source` contains no elements, the returned
|
||
/// index is equal to the buffer's `startIndex`. If `source` contains an
|
||
/// equal or greater number of elements than the buffer can hold, the
|
||
/// returned index is equal to the buffer's `endIndex`.
|
||
///
|
||
/// - Parameter source: A sequence of elements with which to initializer the
|
||
/// buffer.
|
||
/// - Returns: An iterator to any elements of `source` that didn't fit in the
|
||
/// buffer, and an index to the point in the buffer one past the last
|
||
/// element written.
|
||
@inlinable // unsafe-performance
|
||
public func initialize<S: Sequence>(from source: S) -> (S.Iterator, Index)
|
||
where S.Element == Element {
|
||
return source._copyContents(initializing: self)
|
||
}
|
||
}
|
||
|
||
// ${'Local Variables'}:
|
||
// eval: (read-only-mode 1)
|
||
// End:
|