mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Give UnsafePointer versions of CMutablePointer._setIfNonNil and _withBridgeObject/Value. Also provide a version of 'withUnsafePointer' as a staging aid so that UnsafePointer can be used in place of CMutablePointer. Swift SVN r19215
424 lines
13 KiB
Swift
424 lines
13 KiB
Swift
%# -*- mode: 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
% for mutable in (True, False):
|
|
% Self = 'UnsafePointer' if mutable else 'ConstUnsafePointer'
|
|
% a_Self = 'an UnsafePointer' if mutable else 'a ConstUnsafePointer'
|
|
|
|
/// This type stores a pointer to an object of type T. It provides no
|
|
/// automated memory management, and therefore the user must take care
|
|
/// to allocate and free memory appropriately.
|
|
@public struct ${Self}<T> : BidirectionalIndex, Comparable, Hashable,
|
|
LogicValue, NilLiteralConvertible, _Pointer {
|
|
/// The underlying raw (untyped) pointer.
|
|
var value : Builtin.RawPointer
|
|
|
|
/// Construct a null pointer.
|
|
init() {
|
|
self.value = Builtin.inttoptr_Word(0.value)
|
|
}
|
|
|
|
/// Construct ${a_Self} from a builtin raw pointer.
|
|
init(_ value : Builtin.RawPointer) {
|
|
self.value = value
|
|
}
|
|
|
|
/// Convert from an opaque C pointer to a typed pointer
|
|
///
|
|
/// This is a fundamentally unsafe conversion.
|
|
init(_ other : COpaquePointer) {
|
|
value = other.value
|
|
}
|
|
|
|
/// Construct ${a_Self} from a given address in memory.
|
|
///
|
|
/// This is a fundamentally unsafe conversion.
|
|
init(_ value : Int) {
|
|
self.value = Builtin.inttoptr_Word(value.value)
|
|
}
|
|
|
|
/// Convert from an UnsafePointer of a different type.
|
|
///
|
|
/// This is a fundamentally unsafe conversion.
|
|
init<U>(_ from : UnsafePointer<U>) {
|
|
value = from.value
|
|
}
|
|
|
|
/// Convert from a ConstUnsafePointer of a different type.
|
|
///
|
|
/// This is a fundamentally unsafe conversion.
|
|
init<U>(_ from : ConstUnsafePointer<U>) {
|
|
value = from.value
|
|
}
|
|
|
|
// Make nil work with ${Self}.
|
|
@transparent
|
|
static func convertFromNilLiteral() -> ${Self}<T> {
|
|
return .null()
|
|
}
|
|
|
|
static func null() -> ${Self} {
|
|
return ${Self}()
|
|
}
|
|
|
|
% if mutable:
|
|
static func alloc(num: Int) -> ${Self} {
|
|
// Don't bother with overflow checking.
|
|
var size = Int(Builtin.strideof(T.self)) * num
|
|
return ${Self}(Builtin.allocRaw(size.value, Builtin.alignof(T.self)))
|
|
}
|
|
|
|
func dealloc(num: Int) {
|
|
// Overflow checking is actually not required here.
|
|
var size = Int(Builtin.strideof(T.self)) * num
|
|
Builtin.deallocRaw(value, size.value, Builtin.alignof(T.self))
|
|
}
|
|
% end
|
|
|
|
/// Access the underlying raw memory, getting and
|
|
/// setting values.
|
|
var memory : T {
|
|
@transparent get {
|
|
return Builtin.load(value)
|
|
}
|
|
% if mutable:
|
|
@transparent nonmutating set {
|
|
Builtin.assign(newValue, value)
|
|
}
|
|
% end
|
|
}
|
|
|
|
% if mutable:
|
|
/// Initialize the value the pointer points to, to construct
|
|
/// an object where there was no object previously stored.
|
|
func initialize(newvalue: T) {
|
|
Builtin.initialize(newvalue, value)
|
|
}
|
|
|
|
/// Retrieve the value the pointer points to, moving it away
|
|
/// from the location referenced in memory.
|
|
///
|
|
/// Postcondition: The value has been destroyed and the memory must
|
|
/// be initialized before being used again.
|
|
func move() -> T {
|
|
return Builtin.take(value)
|
|
}
|
|
|
|
/// 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`.
|
|
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.
|
|
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()
|
|
}
|
|
}
|
|
|
|
/// Move count values beginning at source into raw memory,
|
|
/// transforming the source values into raw memory.
|
|
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.
|
|
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.
|
|
func initializeFrom<
|
|
C: Collection 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.GeneratorType.Element == T constraint here, because C._Element ==
|
|
// C.GeneratorType.Element in all cases, but doing so crashes the
|
|
// type-checker.
|
|
p++.initialize(reinterpretCast(x))
|
|
}
|
|
}
|
|
|
|
/// Destroy the object the pointer points to.
|
|
func destroy() {
|
|
Builtin.destroy(T.self, value)
|
|
}
|
|
|
|
/// Destroy the `count` objects the pointer points to.
|
|
func destroy(count: Int) {
|
|
_debugPrecondition(count >= 0, "${Self}.destroy with negative count")
|
|
Builtin.destroyArray(T.self, value, count.value)
|
|
}
|
|
% end
|
|
|
|
@transparent
|
|
var _isNull : Bool {
|
|
return self == ${Self}.null()
|
|
}
|
|
|
|
@transparent
|
|
func getLogicValue() -> Bool {
|
|
return !_isNull
|
|
}
|
|
|
|
subscript (i : Int) -> T {
|
|
@transparent
|
|
get {
|
|
return (self + i).memory
|
|
}
|
|
% if mutable:
|
|
@transparent
|
|
nonmutating set {
|
|
(self + i).memory = newValue
|
|
}
|
|
% end
|
|
}
|
|
|
|
% if mutable:
|
|
/// If self was converted from nil, writes the result of invoking body into
|
|
/// the pointee
|
|
func _setIfNonNil(body: () -> T) {
|
|
if self {
|
|
memory = body()
|
|
}
|
|
}
|
|
|
|
/// 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
|
|
func _withBridgeObject<U: AnyObject, R>(
|
|
inout buffer: U?, body: (AutoreleasingUnsafePointer<U?>)->R
|
|
) -> R {
|
|
return self ? body(&buffer) : body(nil)
|
|
}
|
|
|
|
#if ENABLE_POINTER_CONVERSIONS
|
|
/// Return the result of invoking body. If self was converted from
|
|
/// nil, passes nil as the argument. Otherwise, passes the address
|
|
/// of buffer
|
|
@transparent
|
|
func _withBridgeValue<U, R>(
|
|
inout buffer: U, body: (UnsafePointer<U>)->R
|
|
) -> R {
|
|
return self ? body(&buffer) : body(nil)
|
|
}
|
|
#endif
|
|
% end
|
|
|
|
// TODO: Remove this when staging is complete.
|
|
func withUnsafePointer<R>(f: UnsafePointer<T> -> R) -> R {
|
|
return f(UnsafePointer(self))
|
|
}
|
|
|
|
//
|
|
// Protocol conformance
|
|
//
|
|
var hashValue: Int {
|
|
return Int(Builtin.ptrtoint_Word(value))
|
|
}
|
|
func successor() -> ${Self} {
|
|
return self + 1
|
|
}
|
|
func predecessor() -> ${Self} {
|
|
return self - 1
|
|
}
|
|
|
|
#if !ENABLE_POINTER_CONVERSIONS
|
|
//
|
|
// Conversion to C argument pointers
|
|
//
|
|
|
|
// FIXME: Should be in an extension, but that doesn't work yet.
|
|
@transparent @conversion
|
|
func __conversion() -> CMutablePointer<T> {
|
|
return CMutablePointer(owner: _nilNativeObject, value: value)
|
|
}
|
|
func __conversion() -> CMutableVoidPointer {
|
|
return CMutableVoidPointer(owner: _nilNativeObject, value: value)
|
|
}
|
|
@transparent @conversion
|
|
func __conversion() -> CConstPointer<T> {
|
|
return CConstPointer(_nilNativeObject, value)
|
|
}
|
|
@transparent @conversion
|
|
func __conversion() -> CConstVoidPointer {
|
|
return CConstVoidPointer(_nilNativeObject, value)
|
|
}
|
|
@transparent @conversion
|
|
func __conversion() -> AutoreleasingUnsafePointer<T> {
|
|
return AutoreleasingUnsafePointer(value)
|
|
}
|
|
|
|
/// Construct from a CConstPointer.
|
|
///
|
|
/// This is an explicit construction because it is not always safe.
|
|
/// It is only allowed to convert an unscoped pointer, that is, one
|
|
/// that does not have a lifetime-guaranteeing owner reference. To use
|
|
/// a scoped pointer as an UnsafePointer, the withUnsafePointer method
|
|
/// must be used instead.
|
|
init(_ cp: CConstPointer<T>) {
|
|
_precondition(!cp.scoped,
|
|
"scoped CConstPointers must be converted using withUnsafePointer")
|
|
self.value = cp.value
|
|
}
|
|
|
|
/// Construct from a CMutablePointer.
|
|
///
|
|
/// This is an explicit construction because it is not always safe.
|
|
/// It is only allowed to convert an unscoped pointer, that is, one
|
|
/// that does not have a lifetime-guaranteeing owner reference. To use
|
|
/// a scoped pointer as an UnsafePointer, the withUnsafePointer method
|
|
/// must be used instead.
|
|
init(_ cm: CMutablePointer<T>) {
|
|
_precondition(!cm.scoped,
|
|
"scoped CMutablePointers must be converted using withUnsafePointer")
|
|
self.value = cm.value
|
|
}
|
|
|
|
/// Construct from an AutoreleasingUnsafePointer.
|
|
///
|
|
/// This is an explicit construction
|
|
/// because it is unsafe--UnsafePointer's store operations assume that
|
|
/// the pointed-to storage has strong ownership, whereas AutoreleasingUnsafePointers
|
|
/// reference +0 storage. Any values stored through the resulting
|
|
/// UnsafePointer must be autoreleased.
|
|
init(_ op: AutoreleasingUnsafePointer<T>) {
|
|
self.value = op.value
|
|
}
|
|
|
|
/// Construct from a CConstVoidPointer.
|
|
///
|
|
/// This is an explicit construction because it is not always safe.
|
|
/// It is only allowed to convert an unscoped pointer, that is, one
|
|
/// that does not have a lifetime-guaranteeing owner reference. To use
|
|
/// a scoped pointer as an UnsafePointer, the withUnsafePointer method
|
|
/// must be used instead.
|
|
init(_ cp: CConstVoidPointer) {
|
|
_precondition(!cp.scoped,
|
|
"scoped CConstPointers must be converted using withUnsafePointer")
|
|
self.value = cp.value
|
|
}
|
|
|
|
/// Construct from a CMutableVoidPointer.
|
|
///
|
|
/// This is an explicit construction because it is not always safe.
|
|
/// It is only allowed to convert an unscoped pointer, that is, one
|
|
/// that does not have a lifetime-guaranteeing owner reference. To use
|
|
/// a scoped pointer as an UnsafePointer, the withUnsafePointer method
|
|
/// must be used instead.
|
|
init(_ cp: CMutableVoidPointer) {
|
|
_precondition(!cp.scoped,
|
|
"scoped CMutableVoidPointers must be converted using withUnsafePointer")
|
|
self.value = cp.value
|
|
}
|
|
#endif
|
|
}
|
|
|
|
@transparent @public
|
|
func == <T> (lhs: ${Self}<T>, rhs: ${Self}<T>) -> Bool {
|
|
return Bool(Builtin.cmp_eq_RawPointer(lhs.value, rhs.value))
|
|
}
|
|
|
|
@transparent @public
|
|
func < <T>(lhs: ${Self}<T>, rhs: ${Self}<T>) -> Bool {
|
|
return Bool(Builtin.cmp_ult_RawPointer(lhs.value, rhs.value))
|
|
}
|
|
|
|
@transparent @public
|
|
func + <T>(lhs: ${Self}<T>, rhs: Int) -> ${Self}<T> {
|
|
return ${Self}(
|
|
Builtin.gep_Word(lhs.value, (rhs * Int(Builtin.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.value),
|
|
Builtin.ptrtoint_Word(rhs.value)))
|
|
/ Int(Builtin.strideof(T.self))
|
|
}
|
|
|
|
@transparent @public
|
|
@assignment func += <T>(inout lhs: ${Self}<T>, rhs: Int) {
|
|
lhs = lhs + rhs
|
|
}
|
|
|
|
@transparent @public
|
|
@assignment func -= <T>(inout lhs: ${Self}<T>, rhs: Int) {
|
|
lhs = lhs - rhs
|
|
}
|
|
|
|
extension ${Self} : Printable {
|
|
@public var description: String {
|
|
return ""
|
|
}
|
|
}
|
|
% end # for mutable
|
|
|
|
/// A byte-sized thing that isn't designed to interoperate with
|
|
/// any other types; it makes a decent parameter to UnsafePointer when
|
|
/// you just want to do bytewise pointer arithmetic.
|
|
@public struct RawByte {
|
|
let _inaccessible: UInt8
|
|
}
|