Files
swift-mirror/stdlib/public/core/UnsafePointer.swift.gyb

601 lines
19 KiB
Swift

//===--- UnsafePointer.swift.gyb ------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
%import gyb
% for mutable in (True, False):
% Self = 'UnsafeMutablePointer' if mutable else 'UnsafePointer'
% a_Self = 'an `UnsafeMutablePointer`' if mutable else 'an `UnsafePointer`'
/// A raw pointer for accessing data of type `Pointee`. This type
/// provides no automated memory management, and therefore must
/// be handled with great care to ensure safety.
///
/// Instances must be aligned to `alignof(Pointee.self)`, i.e.
/// `(UnsafePointer<Int8>(self) - nil) % alignof(Pointee.self) == 0`
///
/// The memory referenced by an instance can be in one of the following states:
///
/// - Memory is not allocated (for example, pointer is null, or memory has
/// been deallocated previously).
///
/// - Memory is allocated, but value has not been initialized.
///
/// - Memory is allocated and value is initialized.
public struct ${Self}<Pointee>
: RandomAccessIndex, Hashable,
NilLiteralConvertible, _Pointer {
public typealias Distance = Int
/// The underlying raw (untyped) pointer.
public let _rawValue: Builtin.RawPointer
/// Construct ${a_Self} from a builtin raw pointer.
@_transparent
public init(_ _rawValue : Builtin.RawPointer) {
self._rawValue = _rawValue
}
/// Convert from an opaque pointer to a typed pointer.
@_transparent
public init(_ other : OpaquePointer) {
_rawValue = other._rawValue
}
/// Construct ${a_Self} with a given pattern of bits.
@_transparent
public init(bitPattern: Int) {
self._rawValue = Builtin.inttoptr_Word(bitPattern._builtinWordValue)
}
/// Construct ${a_Self} with a given pattern of bits.
@_transparent
public init(bitPattern: UInt) {
self._rawValue = Builtin.inttoptr_Word(bitPattern._builtinWordValue)
}
/// Convert from any `UnsafeMutablePointer`, possibly with a
/// different `Pointee`.
///
/// - Warning: the behavior of accesses to pointee as a type
/// different from that to which it was initialized is undefined.
@_transparent
public init<U>(_ from : UnsafeMutablePointer<U>) {
_rawValue = from._rawValue
}
/// Convert from any `UnsafePointer`, possibly with a
/// different `Pointee`.
///
/// - Warning: the behavior of accesses to pointee as a type
/// different from that to which it was initialized is undefined.
@_transparent
public init<U>(_ from : UnsafePointer<U>) {
_rawValue = from._rawValue
}
/// Create an instance initialized with `nil`.
@_transparent
public init(nilLiteral: ()) {
self._rawValue = _nilRawPointer
}
% if mutable:
/// Allocate and point at uninitialized aligned memory for `count`
/// instances of `Pointee`.
///
/// - Postcondition: The pointee is allocated, but not initialized.
@warn_unused_result
public init(allocatingCapacity count: Int) {
let size = strideof(Pointee.self) * count
self._rawValue =
Builtin.allocRaw(size._builtinWordValue, Builtin.alignof(Pointee.self))
}
/// Deallocate uninitialized memory allocated for `count` instances
/// of `Pointee`.
///
/// - Precondition: The memory is not initialized.
///
/// - Postcondition: The memory has been deallocated.
public func deallocateCapacity(num: Int) {
let size = strideof(Pointee.self) * num
Builtin.deallocRaw(
_rawValue, size._builtinWordValue, Builtin.alignof(Pointee.self))
}
% end
/// Access the `Pointee` instance referenced by `self`.
///
/// - Precondition: the pointee has been initialized with an instance of
/// type `Pointee`.
public var pointee: Pointee {
% if mutable:
@_transparent unsafeAddress {
return UnsafePointer(self)
}
@_transparent nonmutating unsafeMutableAddress {
return self
}
% else:
@_transparent unsafeAddress {
return self
}
% end
}
% if mutable:
/// Initialize `self.pointee` with `count` consecutive copies of `newValue`
///
/// - Precondition: The pointee is not initialized.
/// `count` is non-negative.
///
/// - Postcondition: The pointee is initialized; the value should eventually
/// be destroyed or moved from to avoid leaks.
// FIXME: add tests (since the `count` has been added)
public func initialize(with newValue: Pointee, count: Int = 1) {
_stdlibAssert(count >= 0,
"${Self}.initialize(with:): negative count")
// Must not use `initializeFrom` with a `Collection` as that will introduce
// a cycle.
for offset in 0..<count {
Builtin.initialize(newValue, (self + offset)._rawValue)
}
}
/// Retrieve the `pointee`, returning the referenced memory to an
/// uninitialized state.
///
/// Equivalent to `{ defer { deinitialize() }; return pointee }()`, but
/// more efficient.
///
/// - Precondition: The pointee is initialized.
///
/// - Postcondition: The memory is uninitialized.
@warn_unused_result
public func move() -> Pointee {
return Builtin.take(_rawValue)
}
/// Replace `count` initialized `Pointee`s starting at `self` with
/// the `count` `Pointee`s at `source`, proceeding forward from
/// `self` to `self + count - 1`.
///
/// - Precondition: `count >= 0`
///
/// - Precondition: `self` either precedes `source` or follows
/// `source + count - 1`.
///
/// - Precondition: The `Pointee`s at `self..<self + count` and
/// `source..<source + count` are initialized.
public func assignFrom(source: ${Self}, count: Int) {
_stdlibAssert(
count >= 0, "${Self}.assignFrom with negative count")
_stdlibAssert(
self < source || self >= source + count,
"assignFrom non-following overlapping range; use assignBackwardFrom")
for i in 0..<count {
self[i] = source[i]
}
}
/// Replace `count` initialized `Pointee`s starting at `self` with
/// the `count` `Pointee`s at `source`, proceeding backward from
/// `self + count - 1` to `self`.
///
/// Use `assignBackwardFrom` when copying elements into later memory
/// that may overlap with the source range.
///
/// - Precondition: `count >= 0`
///
/// - Precondition: `source` either precedes `self` or follows
/// `self + count - 1`.
///
/// - Precondition: The `Pointee`s at `self..<self + count` and
/// `source..<source + count` are initialized.
public func assignBackwardFrom(source: ${Self}, count: Int) {
_stdlibAssert(
count >= 0, "${Self}.assignBackwardFrom with negative count")
_stdlibAssert(
source < self || source >= self + count,
"${Self}.assignBackwardFrom non-preceding overlapping range; use assignFrom instead")
var i = count-1
while i >= 0 {
self[i] = source[i]
i -= 1
}
}
/// Initialize memory starting at `self` with `count` `Pointee`s
/// beginning at `source`, proceeding forward from `self` to `self +
/// count - 1`, and returning the source memory to an uninitialized
/// state.
///
/// - Precondition: `count >= 0`
///
/// - Precondition: `self` either precedes `source` or follows `source +
/// count - 1`.
///
/// - Precondition: The memory at `self..<self + count` is uninitialized
/// and the `Pointees` at `source..<source + count` are
/// initialized.
///
/// - Postcondition: The `Pointee`s at `self..<self + count` are
/// initialized and the memory at `source..<source + count` is
/// uninitialized.
public func moveInitializeFrom(source: ${Self}, count: Int) {
_stdlibAssert(
count >= 0, "${Self}.moveInitializeFrom with negative count")
_stdlibAssert(
self < source || self >= source + count,
"${Self}.moveInitializeFrom non-following overlapping range; use moveInitializeBackwardFrom")
Builtin.takeArrayFrontToBack(
Pointee.self, self._rawValue, source._rawValue, count._builtinWordValue)
// This builtin is equivalent to:
// for i in 0..<count {
// (self + i).initialize(with: (source + i).move())
// }
}
/// Initialize memory starting at `self` with `count` `Pointee`s
/// beginning at `source`, proceeding backward from `self + count - 1`
/// to `self`, and returning the source memory to an uninitialized
/// state.
///
/// - Precondition: `count >= 0`
///
/// - Precondition: `source` either precedes `self` or follows
/// `self + count - 1`.
///
/// - Precondition: The memory at `self..<self + count` is uninitialized
/// and the `Pointees` at `source..<source + count` are
/// initialized.
///
/// - Postcondition: The `Pointee`s at `self..<self + count` are
/// initialized and the memory at `source..<source + count` is
/// uninitialized.
public func moveInitializeBackwardFrom(source: ${Self}, count: Int) {
_stdlibAssert(
count >= 0, "${Self}.moveInitializeBackwardFrom with negative count")
_stdlibAssert(
source < self || source >= self + count,
"${Self}.moveInitializeBackwardFrom non-preceding overlapping range; use moveInitializeFrom instead")
Builtin.takeArrayBackToFront(
Pointee.self, self._rawValue, source._rawValue, count._builtinWordValue)
// This builtin is equivalent to:
// var src = source + count
// var dst = self + count
// while dst != self {
// (--dst).initialize(with: (--src).move())
// }
}
/// Initialize memory starting at `self` with `count` `Pointee`s
/// beginning at `source`, proceeding forward from `self` to `self +
/// count - 1`.
///
/// - Precondition: `count >= 0`
///
/// - Precondition: `self` either precedes `source` or follows `source +
/// count - 1`.
///
/// - Precondition: The memory at `self..<self + count` is uninitialized
/// and the `Pointees` at `source..<source + count` are
/// initialized.
///
/// - Postcondition: The `Pointee`s at `self..<self + count` and
/// `source..<source + count` are initialized.
public func initializeFrom(source: ${Self}, count: Int) {
_stdlibAssert(
count >= 0, "${Self}.initializeFrom with negative count")
_stdlibAssert(
self + count <= source || source + count <= self,
"${Self}.initializeFrom non-following overlapping range")
Builtin.copyArray(
Pointee.self, self._rawValue, source._rawValue, count._builtinWordValue)
// This builtin is equivalent to:
// for i in 0..<count {
// (self + i).initialize(with: source[i])
// }
}
/// Initialize memory starting at `self` with the elements of `source`.
///
/// - Precondition: The memory at `self..<self + count` is
/// uninitialized.
///
/// - Postcondition: The `Pointee`s at `self..<self + count` are
/// initialized.
public func initializeFrom<
C : Collection where C.Iterator.Element == Pointee
>(source: C) {
source._copyContents(initializing: self)
}
/// Replace `count` initialized `Pointee`s starting at `self` with
/// the `count` `Pointee`s starting at `source`, returning the
/// source memory to an uninitialized state.
///
/// - Precondition: `count >= 0`
///
/// - Precondition: The source and destination ranges do not overlap
///
/// - Precondition: The `Pointee`s at `self..<self + count` and
/// `source..<source + count` are initialized.
///
/// - Postcondition: The `Pointee`s at `self..<self + count` are
/// initialized and the `Pointees` at `source..<source + count`
/// are uninitialized.
public func moveAssignFrom(source: ${Self}, count: Int) {
_stdlibAssert(
count >= 0, "${Self}.moveAssignFrom with negative count")
_stdlibAssert(
self + count <= source || source + count <= self,
"moveAssignFrom overlapping range")
Builtin.destroyArray(Pointee.self, self._rawValue, count._builtinWordValue)
Builtin.takeArrayFrontToBack(
Pointee.self, self._rawValue, source._rawValue, count._builtinWordValue)
// These builtins are equivalent to:
// for i in 0..<count {
// self[i] = (source + i).move()
// }
}
/// De-initialize the `count` `Pointee`s starting at `self`, returning
/// their memory to an uninitialized state.
///
/// - Precondition: The `Pointee`s at `self..<self + count` are
/// initialized.
///
/// - Postcondition: The memory is uninitialized.
public func deinitialize(count count: Int = 1) {
_stdlibAssert(count >= 0, "${Self}.deinitialize with negative count")
// FIXME: optimization should be implemented, where if the `count` value
// is 1, the `Builtin.destroy(Pointee.self, _rawValue)` gets called.
Builtin.destroyArray(Pointee.self, _rawValue, count._builtinWordValue)
}
% end
@_transparent public
var _isNull : Bool {
return self == nil
}
/// Access the pointee at `self + i`.
///
/// - Precondition: the pointee at `self + i` is initialized.
public subscript(i: Int) -> Pointee {
% if mutable:
@_transparent
unsafeAddress {
return UnsafePointer(self + i)
}
@_transparent
nonmutating unsafeMutableAddress {
return self + i
}
% else:
@_transparent
unsafeAddress {
return self + i
}
% end
}
% if mutable:
/// If self was converted from `nil`, writes the result of invoking body into
/// the pointee.
public // SPI(Foundation)
func _setIfNonNil(@noescape body: () -> Pointee) {
if self != nil {
pointee = body()
}
}
#if _runtime(_ObjC)
/// Returns the result of invoking body. If self was converted from
/// `nil`, passes `nil` as the argument. Otherwise, passes the address
/// of a `Pointee` which is written into buffer before this method returns.
@_transparent public
func _withBridgeObject<U : AnyObject, R>(
buffer: inout U?, @noescape body: AutoreleasingUnsafeMutablePointer<U?> -> R
) -> R {
return self != nil ? body(&buffer) : body(nil)
}
#endif
/// Returns the result of invoking body. If self was converted from
/// `nil`, passes `nil` as the argument. Otherwise, passes the address
/// of buffer.
@_transparent public
func _withBridgeValue<U, R>(
buffer: inout U, @noescape body: UnsafeMutablePointer<U> -> R
) -> R {
return self != nil ? body(&buffer) : body(nil)
}
% end
//
// Protocol conformance
//
/// The hash value.
///
/// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`.
///
/// - Note: The hash value is not guaranteed to be stable across
/// different invocations of the same program. Do not persist the
/// hash value across program runs.
public var hashValue: Int {
return Int(Builtin.ptrtoint_Word(_rawValue))
}
/// Returns the next consecutive position.
public func successor() -> ${Self} {
return self + 1
}
/// Returns the previous consecutive position.
public func predecessor() -> ${Self} {
return self - 1
}
/// Return `end - self`.
public func distance(to x: ${Self}) -> Int {
return x - self
}
/// Return `self + n`.
public func advanced(by n: Int) -> ${Self} {
return self + n
}
}
extension ${Self} : CustomDebugStringConvertible {
/// A textual representation of `self`, suitable for debugging.
public var debugDescription: String {
return _rawPointerToString(_rawValue)
}
}
extension ${Self} : CustomReflectable {
public var customMirror: Mirror {
let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
return Mirror(self, children: ["pointerValue": ptrValue])
}
}
extension ${Self} : CustomPlaygroundQuickLookable {
var summary: String {
let selfType = "${Self}"
let ptrValue = UInt64(bitPattern: Int64(Int(Builtin.ptrtoint_Word(_rawValue))))
return ptrValue == 0 ? "\(selfType)(nil)" : "\(selfType)(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
}
public var customPlaygroundQuickLook: PlaygroundQuickLook {
return .text(summary)
}
}
@_transparent
@warn_unused_result
public func == <Pointee>(
lhs: ${Self}<Pointee>, rhs: ${Self}<Pointee>
) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
}
@_transparent
@warn_unused_result
public func < <Pointee>(lhs: ${Self}<Pointee>, rhs: ${Self}<Pointee>) -> Bool {
return Bool(Builtin.cmp_ult_RawPointer(lhs._rawValue, rhs._rawValue))
}
@_transparent
@warn_unused_result
public func + <Pointee>(lhs: ${Self}<Pointee>, rhs: Int) -> ${Self}<Pointee> {
return ${Self}(Builtin.gep_Word(
lhs._rawValue, (rhs &* strideof(Pointee.self))._builtinWordValue))
}
@_transparent
@warn_unused_result
public func + <Pointee>(lhs: Int,
rhs: ${Self}<Pointee>) -> ${Self}<Pointee> {
return rhs + lhs
}
@_transparent
@warn_unused_result
public func - <Pointee>(lhs: ${Self}<Pointee>, rhs: Int) -> ${Self}<Pointee> {
return lhs + -rhs
}
@_transparent
@warn_unused_result
public func - <Pointee>(lhs: ${Self}<Pointee>, rhs: ${Self}<Pointee>) -> Int {
return
Int(Builtin.sub_Word(Builtin.ptrtoint_Word(lhs._rawValue),
Builtin.ptrtoint_Word(rhs._rawValue)))
/ strideof(Pointee.self)
}
@_transparent
public func += <Pointee>(lhs: inout ${Self}<Pointee>, rhs: Int) {
lhs = lhs + rhs
}
@_transparent
public func -= <Pointee>(lhs: inout ${Self}<Pointee>, rhs: Int) {
lhs = lhs - rhs
}
extension ${Self} {
@available(*, unavailable, renamed="Pointee")
public typealias Memory = Pointee
@available(*, unavailable, message="use 'nil' literal")
public init() {
fatalError("unavailable function can't be called")
}
@available(*, unavailable, message="use the '${Self}(allocatingCapacity:)' initializer")
public static func alloc(num: Int) -> ${Self} {
fatalError("unavailable function can't be called")
}
@available(*, unavailable, renamed="deallocateCapacity")
public func dealloc(num: Int) {
fatalError("unavailable function can't be called")
}
@available(*, unavailable, renamed="pointee")
public var memory: Pointee {
get {
fatalError("unavailable function can't be called")
}
set {
fatalError("unavailable function can't be called")
}
}
@available(*, unavailable, renamed="initialize(with:)")
public func initialize(newvalue: Pointee) {
fatalError("unavailable function can't be called")
}
@available(*, unavailable, renamed="deinitialize(count:)")
public func destroy() {
fatalError("unavailable function can't be called")
}
@available(*, unavailable, renamed="deinitialize(count:)")
public func destroy(count: Int) {
fatalError("unavailable function can't be called")
}
}
% end # for mutable
/// A byte-sized thing that isn't designed to interoperate with
/// any other types; it makes a decent parameter to
/// `UnsafeMutablePointer<Pointee>` when you just want to do bytewise
/// pointer arithmetic.
public // @testable
struct _RawByte {
let _inaccessible: UInt8
}
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End: