mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Like UnsafePointer, without the mutation accessors. gybify UnsafePointer.swift so we can generate both types from the same skeleton. Swift SVN r18937
385 lines
12 KiB
Swift
385 lines
12 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.
|
|
struct ${Self}<T> : BidirectionalIndex, Comparable, Hashable,
|
|
LogicValue, NilLiteralConvertible {
|
|
/// 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
|
|
}
|
|
|
|
//
|
|
// Protocol conformance
|
|
//
|
|
var hashValue: Int {
|
|
return Int(Builtin.ptrtoint_Word(value))
|
|
}
|
|
func succ() -> ${Self} {
|
|
return self + 1
|
|
}
|
|
func pred() -> ${Self} {
|
|
return self - 1
|
|
}
|
|
|
|
//
|
|
// 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
|
|
}
|
|
}
|
|
|
|
@transparent
|
|
func == <T> (lhs: ${Self}<T>, rhs: ${Self}<T>) -> Bool {
|
|
return Bool(Builtin.cmp_eq_RawPointer(lhs.value, rhs.value))
|
|
}
|
|
|
|
@transparent
|
|
func < <T>(lhs: ${Self}<T>, rhs: ${Self}<T>) -> Bool {
|
|
return Bool(Builtin.cmp_ult_RawPointer(lhs.value, rhs.value))
|
|
}
|
|
|
|
@transparent
|
|
func + <T>(lhs: ${Self}<T>, rhs: Int) -> ${Self}<T> {
|
|
return ${Self}(
|
|
Builtin.gep_Word(lhs.value, (rhs * Int(Builtin.strideof(T.self))).value))
|
|
}
|
|
|
|
@transparent
|
|
func + <T>(lhs: Int,
|
|
rhs: ${Self}<T>) -> ${Self}<T> {
|
|
return rhs + lhs
|
|
}
|
|
|
|
@transparent
|
|
func - <T>(lhs: ${Self}<T>, rhs: Int) -> ${Self}<T> {
|
|
return lhs + -rhs
|
|
}
|
|
|
|
@transparent
|
|
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
|
|
@assignment func += <T>(inout lhs: ${Self}<T>, rhs: Int) {
|
|
lhs = lhs + rhs
|
|
}
|
|
|
|
@transparent
|
|
@assignment func -= <T>(inout lhs: ${Self}<T>, rhs: Int) {
|
|
lhs = lhs - rhs
|
|
}
|
|
|
|
extension ${Self} : Printable {
|
|
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.
|
|
struct RawByte {
|
|
let _inaccessible: UInt8
|
|
}
|