mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
505 lines
15 KiB
Swift
505 lines
15 KiB
Swift
//===--- UnsafePointer.swift.gyb ------------------------------*- swift -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 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
|
|
%TMirrorDecl = gyb.parseTemplate("../common/MirrorDecl.gyb")
|
|
%TMirrorConformance = gyb.parseTemplate("../common/MirrorConformance.gyb")
|
|
%TMirrorBoilerplate = gyb.parseTemplate("../common/MirrorBoilerplate.gyb")
|
|
|
|
% for mutable in (True, False):
|
|
% Self = 'UnsafeMutablePointer' if mutable else 'UnsafePointer'
|
|
% a_Self = 'an `UnsafeMutablePointer`' if mutable else 'an `UnsafePointer`'
|
|
% MirrorConformance = gyb.executeTemplate(TMirrorConformance,introspecteeType=Self,genericArgs=['T'],disposition='Struct')
|
|
% MirrorDecl = gyb.executeTemplate(TMirrorDecl,introspecteeType=Self,genericArgs=['T'],disposition='Struct')
|
|
% MirrorBoilerplate = gyb.executeTemplate(TMirrorBoilerplate,introspecteeType=Self,genericArgs=['T'],disposition='Struct')
|
|
|
|
/// A pointer to an object of type `T`. This type provides no automated
|
|
/// memory management, and therefore the user must take care to allocate
|
|
/// and free memory appropriately.
|
|
///
|
|
/// The pointer 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}<T>
|
|
: RandomAccessIndexType, Hashable,
|
|
NilLiteralConvertible, _PointerType {
|
|
|
|
/// The underlying raw (untyped) pointer.
|
|
public var _rawValue : Builtin.RawPointer
|
|
|
|
/// Construct a null pointer.
|
|
@transparent
|
|
public init() {
|
|
self._rawValue = Builtin.inttoptr_Word(0.value)
|
|
}
|
|
|
|
/// Construct ${a_Self} from a builtin raw pointer.
|
|
@transparent
|
|
public init(_ _rawValue : Builtin.RawPointer) {
|
|
self._rawValue = _rawValue
|
|
}
|
|
|
|
/// Convert from an opaque C pointer to a typed pointer
|
|
///
|
|
/// This is a fundamentally unsafe conversion.
|
|
@transparent
|
|
public init(_ other : COpaquePointer) {
|
|
_rawValue = other._rawValue
|
|
}
|
|
|
|
/// Construct ${a_Self} from a given address in memory.
|
|
///
|
|
/// This is a fundamentally unsafe conversion.
|
|
@transparent
|
|
public init(bitPattern: Word) {
|
|
self._rawValue = Builtin.inttoptr_Word(bitPattern.value)
|
|
}
|
|
|
|
/// Construct ${a_Self} from a given address in memory.
|
|
///
|
|
/// This is a fundamentally unsafe conversion.
|
|
@transparent
|
|
public init(bitPattern: UWord) {
|
|
self._rawValue = Builtin.inttoptr_Word(bitPattern.value)
|
|
}
|
|
|
|
/// Convert from an UnsafeMutablePointer of a different type.
|
|
///
|
|
/// This is a fundamentally unsafe conversion.
|
|
@transparent
|
|
public init<U>(_ from : UnsafeMutablePointer<U>) {
|
|
_rawValue = from._rawValue
|
|
}
|
|
|
|
/// Convert from a UnsafePointer of a different type.
|
|
///
|
|
/// This is a fundamentally unsafe conversion.
|
|
@transparent
|
|
public init<U>(_ from : UnsafePointer<U>) {
|
|
_rawValue = from._rawValue
|
|
}
|
|
|
|
/// Create an instance initialized with `nil`.
|
|
@transparent public
|
|
init(nilLiteral: ()) {
|
|
self = .null()
|
|
}
|
|
|
|
/// Return a `nil` instance.
|
|
@transparent
|
|
public static func null() -> ${Self} {
|
|
return ${Self}()
|
|
}
|
|
|
|
% if mutable:
|
|
/// Allocate memory for `num` objects of type `T`.
|
|
///
|
|
/// Postcondition: the memory is allocated, but not initialized.
|
|
public static func alloc(num: Int) -> ${Self} {
|
|
// Don't bother with overflow checking.
|
|
var size = strideof(T.self) * num
|
|
return ${Self}(Builtin.allocRaw(size.value, Builtin.alignof(T.self)))
|
|
}
|
|
|
|
/// Deallocate `num` objects.
|
|
///
|
|
/// :param: num number of objects to deallocate. Should match exactly
|
|
/// the value that was passed to `alloc()` (partial deallocations are not
|
|
/// possible).
|
|
///
|
|
/// Precondition: the memory is not initialized.
|
|
///
|
|
/// Postcondition: the memory has been deallocated.
|
|
public func dealloc(num: Int) {
|
|
// Overflow checking is actually not required here.
|
|
var size = strideof(T.self) * num
|
|
Builtin.deallocRaw(_rawValue, size.value, Builtin.alignof(T.self))
|
|
}
|
|
% end
|
|
|
|
/// Access the underlying raw memory, getting and
|
|
/// setting values.
|
|
public var memory : T {
|
|
% if mutable:
|
|
@transparent address {
|
|
return UnsafePointer(self)
|
|
}
|
|
@transparent nonmutating mutableAddress {
|
|
return self
|
|
}
|
|
% else:
|
|
@transparent address {
|
|
return self
|
|
}
|
|
% end
|
|
}
|
|
|
|
% if mutable:
|
|
/// Initialize the value the pointer points to, to construct
|
|
/// an object where there was no object previously stored.
|
|
///
|
|
/// Precondition: the memory is not initialized.
|
|
///
|
|
/// Postcondition: the memory is initalized; the value should eventually
|
|
/// be destroyed or moved from to avoid leaks.
|
|
public func initialize(newvalue: T) {
|
|
Builtin.initialize(newvalue, _rawValue)
|
|
}
|
|
|
|
/// Retrieve the value the pointer points to, moving it away
|
|
/// from the location referenced in memory.
|
|
///
|
|
/// Equivalent to reading `memory` property and calling `destroy()`,
|
|
/// but more efficient.
|
|
///
|
|
/// Precondition: the memory is initialized.
|
|
///
|
|
/// Postcondition: the value has been destroyed and the memory must
|
|
/// be initialized before being used again.
|
|
public func move() -> T {
|
|
return Builtin.take(_rawValue)
|
|
}
|
|
|
|
/// Move count values beginning at source into uninitialized memory,
|
|
/// transforming the source values into raw memory, proceeding from
|
|
/// the last value to the first. Use this for copying ranges into
|
|
/// later memory that may overlap with the source range.
|
|
///
|
|
/// Requires: either `source` precedes `self` or follows `self + count`.
|
|
public func moveInitializeBackwardFrom(source: ${Self}, count: Int) {
|
|
_debugPrecondition(
|
|
count >= 0, "${Self}.moveInitializeBackwardFrom with negative count")
|
|
_debugPrecondition(
|
|
source <= self || source > self + count,
|
|
"${Self}.moveInitializeBackwardFrom non-preceding overlapping range; use moveInitializeFrom instead")
|
|
var src = source + count
|
|
var dst = self + count
|
|
while dst != self {
|
|
(--dst).initialize((--src).move())
|
|
}
|
|
}
|
|
|
|
/// Assign from count values beginning at source into initialized
|
|
/// memory, transforming the source values into raw memory.
|
|
public func moveAssignFrom(source: ${Self}, count: Int) {
|
|
_debugPrecondition(
|
|
count >= 0, "moveAssignFrom with negative count")
|
|
_debugPrecondition(
|
|
source > self || source < self - count,
|
|
"moveAssignFrom non-following overlapping range")
|
|
for i in 0..<count {
|
|
self[i] = (source + i).move()
|
|
}
|
|
}
|
|
|
|
/// Assign from `count` values beginning at source into initialized
|
|
/// memory, proceeding from the first element to the last.
|
|
public func assignFrom(source: ${Self}, count: Int) {
|
|
_debugPrecondition(
|
|
count >= 0, "moveAssignFrom with negative count")
|
|
_debugPrecondition(
|
|
source > self || source < self - count,
|
|
"moveAssignFrom non-following overlapping range; use assignBackwardFrom")
|
|
for i in 0..<count {
|
|
self[i] = source[i]
|
|
}
|
|
}
|
|
|
|
/// Assign from `count` values beginning at `source` into
|
|
/// initialized memory, proceeding from the last value to the first.
|
|
/// Use this for assigning ranges into later memory that may overlap
|
|
/// with the source range.
|
|
///
|
|
/// Requires: either `source` precedes `self` or follows `self + count`.
|
|
public func assignBackwardFrom(source: ${Self}, count: Int) {
|
|
_debugPrecondition(
|
|
count >= 0, "${Self}.assignBackwardFrom with negative count")
|
|
_debugPrecondition(
|
|
source <= self || source > self + count,
|
|
"${Self}.assignBackwardFrom non-preceding overlapping range; use assignFrom instead")
|
|
for var i = count; --i >= 0; {
|
|
self[i] = source[i]
|
|
}
|
|
}
|
|
|
|
/// Move count values beginning at source into raw memory,
|
|
/// transforming the source values into raw memory.
|
|
public func moveInitializeFrom(source: ${Self}, count: Int) {
|
|
_debugPrecondition(
|
|
count >= 0, "${Self}.moveInitializeFrom with negative count")
|
|
_debugPrecondition(
|
|
source >= self || source < self - count,
|
|
"${Self}.moveInitializeFrom non-following overlapping range; use moveInitializeBackwardFrom")
|
|
for i in 0..<count {
|
|
(self + i).initialize((source + i).move())
|
|
}
|
|
}
|
|
|
|
/// Copy count values beginning at source into raw memory.
|
|
///
|
|
/// Precondition: the memory is not initialized.
|
|
public func initializeFrom(source: ${Self}, count: Int) {
|
|
_debugPrecondition(
|
|
count >= 0, "${Self}.initializeFrom with negative count")
|
|
_debugPrecondition(
|
|
source >= self || source < self - count,
|
|
"${Self}.initializeFrom non-following overlapping range")
|
|
for i in 0..<count {
|
|
(self + i).initialize(source[i])
|
|
}
|
|
}
|
|
|
|
/// Copy the elements of `C` into raw memory.
|
|
///
|
|
/// Precondition: the memory is not initialized.
|
|
public func initializeFrom<
|
|
C: CollectionType where C._Element == T
|
|
>(
|
|
source: C
|
|
) {
|
|
var p = self
|
|
for x in source {
|
|
// FIXME: <rdar://problem/16951692> We should be able to use a
|
|
// C.Generator.Element == T constraint here, because C._Element ==
|
|
// C.Generator.Element in all cases, but doing so crashes the
|
|
// type-checker.
|
|
p++.initialize(unsafeBitCast(x, T.self))
|
|
}
|
|
}
|
|
|
|
/// Destroy the object the pointer points to.
|
|
///
|
|
/// Precondition: the memory is initialized.
|
|
///
|
|
/// Postcondition: the value has been destroyed and the memory must
|
|
/// be initialized before being used again.
|
|
public func destroy() {
|
|
Builtin.destroy(T.self, _rawValue)
|
|
}
|
|
|
|
/// Destroy the `count` objects the pointer points to.
|
|
/// Precondition: the memory is initialized.
|
|
///
|
|
/// Postcondition: the value has been destroyed and the memory must
|
|
/// be initialized before being used again.
|
|
public func destroy(count: Int) {
|
|
_debugPrecondition(count >= 0, "${Self}.destroy with negative count")
|
|
Builtin.destroyArray(T.self, _rawValue, count.value)
|
|
}
|
|
% end
|
|
|
|
@transparent public
|
|
var _isNull : Bool {
|
|
return self == ${Self}.null()
|
|
}
|
|
|
|
/// Access the `i`\ th element of the raw array starting at `self`.
|
|
public subscript (i : Int) -> T {
|
|
% if mutable:
|
|
@transparent
|
|
address {
|
|
return UnsafePointer(self + i)
|
|
}
|
|
@transparent
|
|
nonmutating mutableAddress {
|
|
return self + i
|
|
}
|
|
% else:
|
|
@transparent
|
|
address {
|
|
return self + i
|
|
}
|
|
% end
|
|
}
|
|
|
|
% if mutable:
|
|
/// If self was converted from nil, writes the result of invoking body into
|
|
/// the pointee
|
|
public
|
|
func _setIfNonNil(body: () -> T) {
|
|
if self != nil {
|
|
memory = body()
|
|
}
|
|
}
|
|
|
|
#if _runtime(_ObjC)
|
|
/// Return the result of invoking body. If self was converted from
|
|
/// nil, passes nil as the argument. Otherwise, passes the address
|
|
/// of a T which is written into buffer before this method returns
|
|
@transparent public
|
|
func _withBridgeObject<U: AnyObject, R>(
|
|
inout buffer: U?, body: (AutoreleasingUnsafeMutablePointer<U?>)->R
|
|
) -> R {
|
|
return self != nil ? body(&buffer) : body(nil)
|
|
}
|
|
#endif
|
|
|
|
/// Return 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>(
|
|
inout buffer: U, 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 value after `self`.
|
|
///
|
|
/// Requires: the next value is representable.
|
|
public func successor() -> ${Self} {
|
|
return self + 1
|
|
}
|
|
/// Returns the previous consecutive value before `self`.
|
|
///
|
|
/// Requires: the previous value is representable.
|
|
public func predecessor() -> ${Self} {
|
|
return self - 1
|
|
}
|
|
/// Return the minimum number of applications of `successor` or
|
|
/// `predecessor` required to reach `other` from `self`.
|
|
///
|
|
/// Complexity: O(1).
|
|
public func distanceTo(x: ${Self}) -> Int {
|
|
return x - self
|
|
}
|
|
/// Return `self` offset by `n` steps.
|
|
///
|
|
/// :returns: If `n > 0`, the result of applying `successor` to
|
|
/// `self` `n` times. If `n < 0`, the result of applying
|
|
/// `predecessor` to `self` `-n` times. Otherwise, `self`.
|
|
///
|
|
/// Complexity: O(1)
|
|
public func advancedBy(n: Int) -> ${Self} {
|
|
return self + n
|
|
}
|
|
}
|
|
|
|
extension ${Self} : DebugPrintable {
|
|
/// A textual representation of `self`, suitable for debugging.
|
|
public var debugDescription: String {
|
|
return _rawPointerToString(_rawValue)
|
|
}
|
|
}
|
|
|
|
${MirrorDecl} {
|
|
${MirrorBoilerplate}
|
|
|
|
var count: Int { return 1 }
|
|
|
|
func _getPointerValue() -> UInt64 {
|
|
return UInt64(Int(Builtin.ptrtoint_Word(_value._rawValue)))
|
|
}
|
|
|
|
subscript(i: Int) -> (String, MirrorType) {
|
|
switch i {
|
|
case 0: return ("pointerValue",reflect(_getPointerValue()))
|
|
default: _preconditionFailure("cannot extract this child index")
|
|
}
|
|
}
|
|
|
|
var summary: String {
|
|
let selfType = "${Self}"
|
|
let ptrValue = _getPointerValue()
|
|
if ptrValue == 0 { return "\(selfType)(nil)" }
|
|
return "\(selfType)(0x\(_uint64ToString(ptrValue, radix:16, uppercase:true)))"
|
|
}
|
|
|
|
var quickLookObject: QuickLookObject? { return .Some(.Text(summary)) }
|
|
}
|
|
|
|
${MirrorConformance}
|
|
|
|
@transparent
|
|
public func == <T> (lhs: ${Self}<T>, rhs: ${Self}<T>) -> Bool {
|
|
return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
|
|
}
|
|
|
|
@transparent
|
|
public func < <T>(lhs: ${Self}<T>, rhs: ${Self}<T>) -> Bool {
|
|
return Bool(Builtin.cmp_ult_RawPointer(lhs._rawValue, rhs._rawValue))
|
|
}
|
|
|
|
@transparent
|
|
public func + <T>(lhs: ${Self}<T>, rhs: Int) -> ${Self}<T> {
|
|
return ${Self}(
|
|
Builtin.gep_Word(lhs._rawValue, (rhs &* strideof(T.self)).value))
|
|
}
|
|
|
|
@transparent
|
|
public func + <T>(lhs: Int,
|
|
rhs: ${Self}<T>) -> ${Self}<T> {
|
|
return rhs + lhs
|
|
}
|
|
|
|
@transparent
|
|
public func - <T>(lhs: ${Self}<T>, rhs: Int) -> ${Self}<T> {
|
|
return lhs + -rhs
|
|
}
|
|
|
|
@transparent
|
|
public func - <T>(lhs: ${Self}<T>, rhs: ${Self}<T>) -> Int {
|
|
return
|
|
Int(Builtin.sub_Word(Builtin.ptrtoint_Word(lhs._rawValue),
|
|
Builtin.ptrtoint_Word(rhs._rawValue)))
|
|
/ strideof(T.self)
|
|
}
|
|
|
|
@transparent
|
|
public func += <T>(inout lhs: ${Self}<T>, rhs: Int) {
|
|
lhs = lhs + rhs
|
|
}
|
|
|
|
@transparent
|
|
public func -= <T>(inout lhs: ${Self}<T>, rhs: Int) {
|
|
lhs = lhs - rhs
|
|
}
|
|
% end # for mutable
|
|
|
|
extension UnsafeMutablePointer : SinkType {
|
|
public mutating func put(x: T) {
|
|
self.memory = x
|
|
++self
|
|
}
|
|
}
|
|
|
|
/// A byte-sized thing that isn't designed to interoperate with
|
|
/// any other types; it makes a decent parameter to UnsafeMutablePointer when
|
|
/// you just want to do bytewise pointer arithmetic.
|
|
public struct RawByte {
|
|
let _inaccessible: UInt8
|
|
}
|
|
|
|
// ${'Local Variables'}:
|
|
// eval: (read-only-mode 1)
|
|
// End:
|