Use UnsafeRawPointer in StringCore.

This is another necessary step in introducing changes
for SE-0107: UnsafeRawPointer.

UnsafeRawPointer is great for bytewise pointer operations.

OpaquePointer goes away.

The _RawByte type goes away.

StringBuffer always binds memory to the correct CodeUnit
when allocating memory.

Before accessing the string, a dynamic element width check
allows us to assume the bound memory type.

Generic entry points like atomicCompareExchange no longer handle
both kinds of pointers. Normally that's good because you
should not be using generics in that case, just upcast
to raw pointer. However, with pointers-to-pointers
you can't do that.
This commit is contained in:
Andrew Trick
2016-07-26 18:28:39 -07:00
parent 3e2372b6a3
commit 9886e4ef54
12 changed files with 133 additions and 119 deletions

View File

@@ -35,7 +35,7 @@ vectorElementNames = [
public func _indexHomogeneousValue<TTT, T>(_ aggregate: UnsafePointer<TTT>,
_ index: Int) -> T {
return UnsafeRawPointer(aggregate).load(
fromByteOffset: index * strideof(T), as: T.self)
fromByteOffset: index * strideof(T.self), as: T.self)
}
%{

View File

@@ -183,7 +183,7 @@ public struct Character :
}
else {
if let native = s._core.nativeBuffer,
native.start == UnsafeMutablePointer(s._core._baseAddress!) {
native.start == s._core._baseAddress! {
_representation = .large(native._storage)
return
}

View File

@@ -20,19 +20,21 @@ import SwiftShims
// Atomics
//===----------------------------------------------------------------------===//
public typealias _PointerToPointer = UnsafeMutablePointer<UnsafeRawPointer?>
@_transparent
public // @testable
func _stdlib_atomicCompareExchangeStrongPtrImpl(
object target: UnsafeMutablePointer<UnsafeMutableRawPointer?>,
expected: UnsafeMutablePointer<UnsafeMutableRawPointer?>,
desired: UnsafeMutableRawPointer?) -> Bool {
func _stdlib_atomicCompareExchangeStrongPtr(
object target: _PointerToPointer,
expected: _PointerToPointer,
desired: UnsafeRawPointer?) -> Bool {
// We use Builtin.Word here because Builtin.RawPointer can't be nil.
let (oldValue, won) = Builtin.cmpxchg_seqcst_seqcst_Word(
target._rawValue,
UInt(bitPattern: expected.pointee)._builtinWordValue,
UInt(bitPattern: desired)._builtinWordValue)
expected.pointee = UnsafeMutableRawPointer(bitPattern: Int(oldValue))
expected.pointee = UnsafeRawPointer(bitPattern: Int(oldValue))
return Bool(won)
}
@@ -70,12 +72,12 @@ func _stdlib_atomicCompareExchangeStrongPtr<T>(
object target: UnsafeMutablePointer<UnsafeMutablePointer<T>${optional}>,
expected: UnsafeMutablePointer<UnsafeMutablePointer<T>${optional}>,
desired: UnsafeMutablePointer<T>${optional}) -> Bool {
return _stdlib_atomicCompareExchangeStrongPtrImpl(
object: UnsafeMutablePointer(target),
expected: UnsafeMutablePointer(expected),
desired: UnsafeMutablePointer(desired))
return _stdlib_atomicCompareExchangeStrongPtr(
object: unsafeBitCast(target, to: _PointerToPointer.self),
expected: unsafeBitCast(expected, to: _PointerToPointer.self),
desired: unsafeBitCast(desired, to: Optional<UnsafeRawPointer>.self))
}
% end
% end # optional
@_transparent
@discardableResult
@@ -83,10 +85,10 @@ public // @testable
func _stdlib_atomicInitializeARCRef(
object target: UnsafeMutablePointer<AnyObject?>,
desired: AnyObject) -> Bool {
var expected: UnsafeMutableRawPointer? = nil
var expected: UnsafeRawPointer? = nil
let desiredPtr = Unmanaged.passRetained(desired).toOpaque()
let wonRace = _stdlib_atomicCompareExchangeStrongPtrImpl(
object: UnsafeMutablePointer(target),
let wonRace = _stdlib_atomicCompareExchangeStrongPtr(
object: unsafeBitCast(target, to: _PointerToPointer.self),
expected: &expected,
desired: desiredPtr)
if !wonRace {

View File

@@ -400,7 +400,7 @@ extension String : _ExpressibleByBuiltinUTF16StringLiteral {
) {
self = String(
_StringCore(
baseAddress: OpaquePointer(start),
baseAddress: UnsafeMutableRawPointer(start),
count: Int(utf16CodeUnitCount),
elementShift: 1,
hasCocoaBuffer: false,
@@ -418,7 +418,7 @@ extension String : _ExpressibleByBuiltinStringLiteral {
if Bool(isASCII) {
self = String(
_StringCore(
baseAddress: OpaquePointer(start),
baseAddress: UnsafeMutableRawPointer(start),
count: Int(utf8CodeUnitCount),
elementShift: 0,
hasCocoaBuffer: false,
@@ -699,13 +699,15 @@ extension String : Hashable {
}
#else
if self._core.isASCII {
return _swift_stdlib_unicode_hash_ascii(
UnsafeMutablePointer<Int8>(_core.startASCII),
Int32(_core.count))
return _core.startASCII.withMemoryRebound(
to: CChar.self, capacity: _core.count) {
_swift_stdlib_unicode_hash_ascii($0, Int32(_core.count))
}
} else {
return _swift_stdlib_unicode_hash(
UnsafeMutablePointer<UInt16>(_core.startUTF16),
Int32(_core.count))
return _core.startUTF16.withMemoryRebound(
to: UInt16.self, capacity: _core.count) {
_swift_stdlib_unicode_hash($0, Int32(_core.count))
}
}
#endif
}
@@ -821,7 +823,8 @@ internal func _nativeUnicodeLowercaseString(_ str: String) -> String {
capacity: str._core.count, initialSize: str._core.count, elementWidth: 2)
// Try to write it out to the same length.
let dest = UnsafeMutablePointer<UTF16.CodeUnit>(buffer.start)
let dest = buffer.start.bindMemory(
to: UTF16.CodeUnit.self, capacity: str._core.count)
let z = _swift_stdlib_unicode_strToLower(
dest, Int32(str._core.count),
str._core.startUTF16, Int32(str._core.count))
@@ -831,7 +834,8 @@ internal func _nativeUnicodeLowercaseString(_ str: String) -> String {
if correctSize != str._core.count {
buffer = _StringBuffer(
capacity: correctSize, initialSize: correctSize, elementWidth: 2)
let dest = UnsafeMutablePointer<UTF16.CodeUnit>(buffer.start)
let dest = buffer.start.bindMemory(
to: UTF16.CodeUnit.self, capacity: str._core.count)
_swift_stdlib_unicode_strToLower(
dest, Int32(correctSize), str._core.startUTF16, Int32(str._core.count))
}
@@ -844,7 +848,8 @@ internal func _nativeUnicodeUppercaseString(_ str: String) -> String {
capacity: str._core.count, initialSize: str._core.count, elementWidth: 2)
// Try to write it out to the same length.
let dest = UnsafeMutablePointer<UTF16.CodeUnit>(buffer.start)
let dest = buffer.start.bindMemory(
to: UTF16.CodeUnit.self, capacity: str._core.count)
let z = _swift_stdlib_unicode_strToUpper(
dest, Int32(str._core.count),
str._core.startUTF16, Int32(str._core.count))
@@ -854,7 +859,8 @@ internal func _nativeUnicodeUppercaseString(_ str: String) -> String {
if correctSize != str._core.count {
buffer = _StringBuffer(
capacity: correctSize, initialSize: correctSize, elementWidth: 2)
let dest = UnsafeMutablePointer<UTF16.CodeUnit>(buffer.start)
let dest = buffer.start.bindMemory(
to: UTF16.CodeUnit.self, capacity: str._core.count)
_swift_stdlib_unicode_strToUpper(
dest, Int32(correctSize), str._core.startUTF16, Int32(str._core.count))
}
@@ -904,7 +910,7 @@ extension String {
let source = self._core.startASCII
let buffer = _StringBuffer(
capacity: count, initialSize: count, elementWidth: 1)
let dest = UnsafeMutablePointer<UInt8>(buffer.start)
let dest = buffer.start
for i in 0..<count {
// For each character in the string, we lookup if it should be shifted
// in our ascii table, then we return 0x20 if it should, 0x0 if not.
@@ -923,7 +929,8 @@ extension String {
// Since we are left with either 0x0 or 0x20, we can safely truncate to
// a UInt8 and add to our ASCII value (this will not overflow numbers in
// the ASCII range).
dest[i] = value &+ UInt8(truncatingBitPattern: add)
dest.storeBytes(of: value &+ UInt8(truncatingBitPattern: add),
toByteOffset: i, as: UInt8.self)
}
return String(_storage: buffer)
}
@@ -953,7 +960,7 @@ extension String {
let source = self._core.startASCII
let buffer = _StringBuffer(
capacity: count, initialSize: count, elementWidth: 1)
let dest = UnsafeMutablePointer<UInt8>(buffer.start)
let dest = buffer.start
for i in 0..<count {
// See the comment above in lowercaseString.
let value = source[i]
@@ -961,7 +968,8 @@ extension String {
_asciiLowerCaseTable >>
UInt64(((value &- 1) & 0b0111_1111) >> 1)
let add = (isLower & 0x1) << 5
dest[i] = value &- UInt8(truncatingBitPattern: add)
dest.storeBytes(of: value &- UInt8(truncatingBitPattern: add),
toByteOffset: i, as: UInt8.self)
}
return String(_storage: buffer)
}

View File

@@ -54,7 +54,7 @@ func _cocoaStringToSwiftString_NonASCII(
let start = _stdlib_binary_CFStringGetCharactersPtr(cfImmutableValue)
return String(_StringCore(
baseAddress: OpaquePointer(start),
baseAddress: start,
count: length,
elementShift: 1,
hasCocoaBuffer: true,
@@ -81,7 +81,7 @@ internal func _cocoaStringToContiguous(
_swift_stdlib_CFStringGetCharacters(
source, _swift_shims_CFRange(location: startIndex, length: count),
UnsafeMutablePointer<_swift_shims_UniChar>(buffer.start))
buffer.start.assumingMemoryBound(to: _swift_shims_UniChar.self))
return buffer
}
@@ -163,13 +163,13 @@ extension String {
// start will hold the base pointer of contiguous storage, if it
// is found.
var start: OpaquePointer?
var start: UnsafeMutableRawPointer?
let isUTF16 = (nulTerminatedASCII == nil)
if isUTF16 {
let utf16Buf = _swift_stdlib_CFStringGetCharactersPtr(cfImmutableValue)
start = OpaquePointer(utf16Buf)
start = UnsafeMutableRawPointer(mutating: utf16Buf)
} else {
start = OpaquePointer(nulTerminatedASCII)
start = UnsafeMutableRawPointer(mutating: nulTerminatedASCII)
}
self._core = _StringCore(

View File

@@ -19,7 +19,7 @@ struct _StringBufferIVars {
}
internal init(
_usedEnd: UnsafeMutablePointer<_RawByte>,
_usedEnd: UnsafeMutableRawPointer,
byteCapacity: Int,
elementWidth: Int
) {
@@ -31,7 +31,7 @@ struct _StringBufferIVars {
// This stored property should be stored at offset zero. We perform atomic
// operations on it using _HeapBuffer's pointer.
var usedEnd: UnsafeMutablePointer<_RawByte>?
var usedEnd: UnsafeMutableRawPointer?
var capacityAndElementShift: Int
var byteCapacity: Int {
@@ -78,6 +78,14 @@ public struct _StringBuffer {
_StringBufferIVars(_elementWidth: elementWidth),
(capacity + capacityBump + divRound) >> divRound
)
// This conditional branch should fold away during code gen.
if elementShift == 0 {
start.bindMemory(to: UTF8.CodeUnit.self, capacity: initialSize)
}
else {
start.bindMemory(to: UTF16.CodeUnit.self, capacity: initialSize)
}
self.usedEnd = start + (initialSize << elementShift)
_storage.value.capacityAndElementShift
= ((_storage._capacity() - capacityBump) << 1) + elementShift
@@ -107,7 +115,7 @@ public struct _StringBuffer {
elementWidth: isAscii ? 1 : 2)
if isAscii {
var p = UnsafeMutablePointer<UTF8.CodeUnit>(result.start)
var p = result.start.assumingMemoryBound(to: UTF8.CodeUnit.self)
let sink: (UTF32.CodeUnit) -> Void = {
p.pointee = UTF8.CodeUnit($0)
p += 1
@@ -137,12 +145,12 @@ public struct _StringBuffer {
/// A pointer to the start of this buffer's data area.
public // @testable
var start: UnsafeMutablePointer<_RawByte> {
return UnsafeMutablePointer(_storage.baseAddress)
var start: UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(_storage.baseAddress)
}
/// A past-the-end pointer for this buffer's stored data.
var usedEnd: UnsafeMutablePointer<_RawByte> {
var usedEnd: UnsafeMutableRawPointer {
get {
return _storage.value.usedEnd!
}
@@ -156,7 +164,7 @@ public struct _StringBuffer {
}
/// A past-the-end pointer for this buffer's available storage.
var capacityEnd: UnsafeMutablePointer<_RawByte> {
var capacityEnd: UnsafeMutableRawPointer {
return start + _storage.value.byteCapacity
}
@@ -181,11 +189,11 @@ public struct _StringBuffer {
// two separate phases. Operations with one-phase growth should use
// "grow()," below.
func hasCapacity(
_ cap: Int, forSubRange r: Range<UnsafePointer<_RawByte>>
_ cap: Int, forSubRange r: Range<UnsafeRawPointer>
) -> Bool {
// The substring to be grown could be pointing in the middle of this
// _StringBuffer.
let offset = (r.lowerBound - UnsafePointer(start)) >> elementShift
let offset = (r.lowerBound - UnsafeRawPointer(start)) >> elementShift
return cap + offset <= capacity
}
@@ -202,13 +210,14 @@ public struct _StringBuffer {
@inline(__always)
@discardableResult
mutating func grow(
oldBounds bounds: Range<UnsafePointer<_RawByte>>, newUsedCount: Int
oldBounds bounds: Range<UnsafeRawPointer>, newUsedCount: Int
) -> Bool {
var newUsedCount = newUsedCount
// The substring to be grown could be pointing in the middle of this
// _StringBuffer. Adjust the size so that it covers the imaginary
// substring from the start of the buffer to `oldUsedEnd`.
newUsedCount += (bounds.lowerBound - UnsafePointer(start)) >> elementShift
newUsedCount
+= (bounds.lowerBound - UnsafeRawPointer(start)) >> elementShift
if _slowPath(newUsedCount > capacity) {
return false
@@ -230,11 +239,14 @@ public struct _StringBuffer {
// usedEnd = newUsedEnd
// return true
// }
let usedEndPhysicalPtr =
UnsafeMutablePointer<UnsafeMutablePointer<_RawByte>>(_storage._value)
var expected = UnsafeMutablePointer<_RawByte>(bounds.upperBound)
// &StringBufferIVars.usedEnd
let usedEndPhysicalPtr = _PointerToPointer(_storage._value)
// Create a temp var to hold the exchanged `expected` value.
var expected : UnsafeRawPointer? = bounds.upperBound
if _stdlib_atomicCompareExchangeStrongPtr(
object: usedEndPhysicalPtr, expected: &expected, desired: newUsedEnd) {
object: usedEndPhysicalPtr, expected: &expected,
desired: UnsafeRawPointer(newUsedEnd)) {
return true
}

View File

@@ -28,13 +28,13 @@
public struct _StringCore {
//===--------------------------------------------------------------------===//
// Internals
public var _baseAddress: OpaquePointer?
public var _baseAddress: UnsafeMutableRawPointer?
var _countAndFlags: UInt
public var _owner: AnyObject?
/// (private) create the implementation of a string from its component parts.
init(
baseAddress: OpaquePointer?,
baseAddress: UnsafeMutableRawPointer?,
_countAndFlags: UInt,
owner: AnyObject?
) {
@@ -68,10 +68,9 @@ public struct _StringCore {
_sanityCheck(!hasCocoaBuffer)
_sanityCheck(elementWidth == buffer.elementWidth,
"_StringCore elementWidth doesn't match its buffer's")
_sanityCheck(UnsafeMutablePointer(_baseAddress!) >= buffer.start)
_sanityCheck(UnsafeMutablePointer(_baseAddress!) <= buffer.usedEnd)
_sanityCheck(
UnsafeMutablePointer(_pointer(toElementAt: count)) <= buffer.usedEnd)
_sanityCheck(_baseAddress! >= buffer.start)
_sanityCheck(_baseAddress! <= buffer.usedEnd)
_sanityCheck(_pointer(toElementAt: count) <= buffer.usedEnd)
}
#endif
}
@@ -97,29 +96,28 @@ public struct _StringCore {
/// storage. Caveats: The string must have contiguous storage; the
/// element may be 1 or 2 bytes wide, depending on elementWidth; the
/// result may be null if the string is empty.
func _pointer(toElementAt n: Int) -> OpaquePointer {
func _pointer(toElementAt n: Int) -> UnsafeMutableRawPointer {
_sanityCheck(hasContiguousStorage && n >= 0 && n <= count)
return OpaquePointer(
UnsafeMutablePointer<_RawByte>(_baseAddress!) + (n << elementShift))
return _baseAddress! + (n << elementShift)
}
static func _copyElements(
_ srcStart: OpaquePointer, srcElementWidth: Int,
dstStart: OpaquePointer, dstElementWidth: Int,
_ srcStart: UnsafeMutableRawPointer, srcElementWidth: Int,
dstStart: UnsafeMutableRawPointer, dstElementWidth: Int,
count: Int
) {
// Copy the old stuff into the new storage
if _fastPath(srcElementWidth == dstElementWidth) {
// No change in storage width; we can use memcpy
_memcpy(
dest: UnsafeMutablePointer(dstStart),
src: UnsafeMutablePointer(srcStart),
dest: dstStart,
src: srcStart,
size: UInt(count << (srcElementWidth - 1)))
}
else if (srcElementWidth < dstElementWidth) {
// Widening ASCII to UTF-16; we need to copy the bytes manually
var dest = UnsafeMutablePointer<UTF16.CodeUnit>(dstStart)
var src = UnsafeMutablePointer<UTF8.CodeUnit>(srcStart)
var dest = dstStart.assumingMemoryBound(to: UTF16.CodeUnit.self)
var src = srcStart.assumingMemoryBound(to: UTF8.CodeUnit.self)
let srcEnd = src + count
while (src != srcEnd) {
dest.pointee = UTF16.CodeUnit(src.pointee)
@@ -129,8 +127,8 @@ public struct _StringCore {
}
else {
// Narrowing UTF-16 to ASCII; we need to copy the bytes manually
var dest = UnsafeMutablePointer<UTF8.CodeUnit>(dstStart)
var src = UnsafeMutablePointer<UTF16.CodeUnit>(srcStart)
var dest = dstStart.assumingMemoryBound(to: UTF8.CodeUnit.self)
var src = srcStart.assumingMemoryBound(to: UTF16.CodeUnit.self)
let srcEnd = src + count
while (src != srcEnd) {
dest.pointee = UTF8.CodeUnit(src.pointee)
@@ -143,7 +141,7 @@ public struct _StringCore {
//===--------------------------------------------------------------------===//
// Initialization
public init(
baseAddress: OpaquePointer?,
baseAddress: UnsafeMutableRawPointer?,
count: Int,
elementShift: Int,
hasCocoaBuffer: Bool,
@@ -165,7 +163,7 @@ public struct _StringCore {
/// Create a _StringCore that covers the entire length of the _StringBuffer.
init(_ buffer: _StringBuffer) {
self = _StringCore(
baseAddress: OpaquePointer(buffer.start),
baseAddress: buffer.start,
count: buffer.usedCount,
elementShift: buffer.elementShift,
hasCocoaBuffer: false,
@@ -199,7 +197,7 @@ public struct _StringCore {
}
/// Left shift amount to apply to an offset N so that when
/// added to a UnsafeMutablePointer<_RawByte>, it traverses N elements.
/// added to a UnsafeMutableRawPointer, it traverses N elements.
var elementShift: Int {
return Int(_countAndFlags >> (UInt._sizeInBits - 1))
}
@@ -227,7 +225,7 @@ public struct _StringCore {
public var startASCII: UnsafeMutablePointer<UTF8.CodeUnit> {
_sanityCheck(elementWidth == 1, "String does not contain contiguous ASCII")
return UnsafeMutablePointer(_baseAddress!)
return _baseAddress!.assumingMemoryBound(to: UTF8.CodeUnit.self)
}
/// True iff a contiguous ASCII buffer available.
@@ -239,7 +237,7 @@ public struct _StringCore {
_sanityCheck(
count == 0 || elementWidth == 2,
"String does not contain contiguous UTF-16")
return UnsafeMutablePointer(_baseAddress!)
return _baseAddress!.assumingMemoryBound(to: UTF16.CodeUnit.self)
}
/// the native _StringBuffer, if any, or `nil`.
@@ -336,7 +334,7 @@ public struct _StringCore {
if _fastPath(_baseAddress != nil) {
if _fastPath(elementWidth == 1) {
for x in UnsafeBufferPointer(
start: UnsafeMutablePointer<UTF8.CodeUnit>(_baseAddress!),
start: _baseAddress!.assumingMemoryBound(to: UTF8.CodeUnit.self),
count: count
) {
Encoding.encode(UnicodeScalar(x), into: processCodeUnit)
@@ -345,7 +343,7 @@ public struct _StringCore {
else {
let hadError = transcode(
UnsafeBufferPointer(
start: UnsafeMutablePointer<UTF16.CodeUnit>(_baseAddress!),
start: _baseAddress!.assumingMemoryBound(to: UTF16.CodeUnit.self),
count: count
).makeIterator(),
from: UTF16.self,
@@ -381,7 +379,7 @@ public struct _StringCore {
/// existing buffer, the suggested new capacity will at least double
/// the existing buffer's storage.
mutating func _claimCapacity(
_ newSize: Int, minElementWidth: Int) -> (Int, OpaquePointer?) {
_ newSize: Int, minElementWidth: Int) -> (Int, UnsafeMutableRawPointer?) {
if _fastPath((nativeBuffer != nil) && elementWidth >= minElementWidth) {
var buffer = nativeBuffer!
@@ -394,7 +392,7 @@ public struct _StringCore {
// Attempt to claim unused capacity in the buffer
if _fastPath(
buffer.grow(
oldBounds: UnsafePointer(usedStart)..<UnsafePointer(usedEnd),
oldBounds: UnsafeRawPointer(usedStart)..<UnsafeRawPointer(usedEnd),
newUsedCount: newSize)
) {
count = newSize
@@ -415,7 +413,7 @@ public struct _StringCore {
/// you must immediately copy valid data into that storage.
mutating func _growBuffer(
_ newSize: Int, minElementWidth: Int
) -> OpaquePointer {
) -> UnsafeMutableRawPointer {
let (newCapacity, existingStorage)
= _claimCapacity(newSize, minElementWidth: minElementWidth)
@@ -455,7 +453,7 @@ public struct _StringCore {
if hasContiguousStorage {
_StringCore._copyElements(
_baseAddress!, srcElementWidth: elementWidth,
dstStart: OpaquePointer(newStorage.start),
dstStart: UnsafeMutableRawPointer(newStorage.start),
dstElementWidth: newElementWidth, count: oldCount)
}
else {
@@ -465,7 +463,8 @@ public struct _StringCore {
// FIXME: can we get Cocoa to tell us quickly that an opaque
// string is ASCII? Do we care much about that edge case?
_sanityCheck(newStorage.elementShift == 1)
_cocoaStringReadAll(cocoaBuffer!, UnsafeMutablePointer(newStorage.start))
_cocoaStringReadAll(cocoaBuffer!,
newStorage.start.assumingMemoryBound(to: UTF16.CodeUnit.self))
#else
_sanityCheckFailure("_copyInPlace: non-native string without objc runtime")
#endif
@@ -502,15 +501,14 @@ public struct _StringCore {
count + utf16Width, minElementWidth: minBytesPerCodeUnit)
if _fastPath(elementWidth == 1) {
_sanityCheck(
_pointer(toElementAt:count)
== OpaquePointer(UnsafeMutablePointer<_RawByte>(destination) + 1))
_sanityCheck(_pointer(toElementAt:count) == destination + 1)
UnsafeMutablePointer<UTF8.CodeUnit>(destination)[0] = UTF8.CodeUnit(u0)
destination.assumingMemoryBound(to: UTF8.CodeUnit.self)[0]
= UTF8.CodeUnit(u0)
}
else {
let destination16
= UnsafeMutablePointer<UTF16.CodeUnit>(destination._rawValue)
= destination.assumingMemoryBound(to: UTF16.CodeUnit.self)
destination16[0] = u0
if u1 != nil {
@@ -539,7 +537,8 @@ public struct _StringCore {
else {
#if _runtime(_ObjC)
_sanityCheck(elementWidth == 2)
_cocoaStringReadAll(rhs.cocoaBuffer!, UnsafeMutablePointer(destination))
_cocoaStringReadAll(rhs.cocoaBuffer!,
destination.assumingMemoryBound(to: UTF16.CodeUnit.self))
#else
_sanityCheckFailure("subscript: non-native string without objc runtime")
#endif
@@ -560,7 +559,7 @@ public struct _StringCore {
}
let unsafeBuffer =
UnsafeBufferPointer(
start: UnsafeMutablePointer<UTF16.CodeUnit>(_baseAddress),
start: _baseAddress!.assumingMemoryBound(to: UTF16.CodeUnit.self),
count: count)
return !unsafeBuffer.contains { $0 > 0x7f }
}
@@ -618,24 +617,23 @@ extension _StringCore : RangeReplaceableCollection {
) ? _claimCapacity(newCount, minElementWidth: width).1 : nil
if _fastPath(existingStorage != nil) {
let rangeStart = UnsafeMutablePointer<UInt8>(
_pointer(toElementAt:bounds.lowerBound))
let rangeStart = _pointer(toElementAt:bounds.lowerBound)
let tailStart = rangeStart + (replacedCount << elementShift)
if growth > 0 {
(tailStart + (growth << elementShift)).assign(
(tailStart + (growth << elementShift)).copyBytes(
from: tailStart, count: tailCount << elementShift)
}
if _fastPath(elementWidth == 1) {
var dst = rangeStart
var dst = rangeStart.assumingMemoryBound(to: UTF8.CodeUnit.self)
for u in newElements {
dst.pointee = UInt8(truncatingBitPattern: u)
dst += 1
}
}
else {
var dst = UnsafeMutablePointer<UTF16.CodeUnit>(rangeStart)
var dst = rangeStart.assumingMemoryBound(to: UTF16.CodeUnit.self)
for u in newElements {
dst.pointee = u
dst += 1
@@ -643,7 +641,7 @@ extension _StringCore : RangeReplaceableCollection {
}
if growth < 0 {
(tailStart + (growth << elementShift)).assign(
(tailStart + (growth << elementShift)).copyBytes(
from: tailStart, count: tailCount << elementShift)
}
}
@@ -668,8 +666,9 @@ extension _StringCore : RangeReplaceableCollection {
if _fastPath(!hasCocoaBuffer) {
if _fastPath(isKnownUniquelyReferenced(&_owner)) {
let bounds: Range<UnsafePointer<_RawByte>>
= UnsafePointer(_pointer(toElementAt:0))..<UnsafePointer(_pointer(toElementAt:count))
let bounds: Range<UnsafeRawPointer>
= UnsafeRawPointer(_pointer(toElementAt:0))
..< UnsafeRawPointer(_pointer(toElementAt:count))
if _fastPath(nativeBuffer!.hasCapacity(n, forSubRange: bounds)) {
return
@@ -700,13 +699,15 @@ extension _StringCore : RangeReplaceableCollection {
let newSize = count + growth
let destination = _growBuffer(newSize, minElementWidth: width)
if elementWidth == 1 {
let destination8 = UnsafeMutablePointer<UTF8.CodeUnit>(destination)
let destination8
= destination.assumingMemoryBound(to: UTF8.CodeUnit.self)
for i in 0..<growth {
destination8[i] = UTF8.CodeUnit(iter.next()!)
}
}
else {
let destination16 = UnsafeMutablePointer<UTF16.CodeUnit>(destination)
let destination16
= destination.assumingMemoryBound(to: UTF16.CodeUnit.self)
for i in 0..<growth {
destination16[i] = iter.next()!
}
@@ -723,7 +724,6 @@ extension _StringCore : RangeReplaceableCollection {
// storage have a non-NULL base address.
var _emptyStringStorage: UInt32 = 0
var _emptyStringBase: OpaquePointer {
return OpaquePointer(
UnsafeMutablePointer<UInt16>(Builtin.addressof(&_emptyStringStorage)))
var _emptyStringBase: UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(Builtin.addressof(&_emptyStringStorage))
}

View File

@@ -43,8 +43,8 @@ extension _StringCore {
var result: _UTF8Chunk = ~0 // Start with all bits set
_memcpy(
dest: UnsafeMutablePointer(Builtin.addressof(&result)),
src: UnsafeMutablePointer(startASCII + i),
dest: UnsafeMutableRawPointer(Builtin.addressof(&result)),
src: startASCII + i,
size: numericCast(utf16Count))
// Convert the _UTF8Chunk into host endianness.

View File

@@ -204,13 +204,15 @@ extension String {
self._baseSet = true
if _base.isASCII {
self._ascii = true
self._asciiBase = UnsafeBufferPointer<UInt8>(
start: UnsafePointer(_base._baseAddress),
self._asciiBase = UnsafeBufferPointer(
start: _base._baseAddress?.assumingMemoryBound(
to: UTF8.CodeUnit.self),
count: _base.count).makeIterator()
} else {
self._ascii = false
self._base = UnsafeBufferPointer<UInt16>(
start: UnsafePointer(_base._baseAddress),
start: _base._baseAddress?.assumingMemoryBound(
to: UTF16.CodeUnit.self),
count: _base.count).makeIterator()
}
} else {

View File

@@ -629,16 +629,6 @@ extension UInt {
}
% 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.
@_fixed_layout
public // @testable
struct _RawByte {
let _inaccessible: UInt8
}
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:

View File

@@ -37,8 +37,8 @@ func repr(_ x: _StringCore) -> String {
if x.hasContiguousStorage {
if let b = x.nativeBuffer {
var offset = x.elementWidth == 2
? UnsafeMutablePointer(b.start) - x.startUTF16
: UnsafeMutablePointer(b.start) - x.startASCII
? b.start - UnsafeMutableRawPointer(x.startUTF16)
: b.start - UnsafeMutableRawPointer(x.startASCII)
return "Contiguous(owner: "
+ "\(hexAddr(x._owner))[\(offset)...\(x.count + offset)]"
+ ", capacity = \(b.capacity))"

View File

@@ -39,8 +39,8 @@ func repr(_ x: _StringCore) -> String {
if x.hasContiguousStorage {
if let b = x.nativeBuffer {
var offset = x.elementWidth == 2
? UnsafeMutablePointer(b.start) - x.startUTF16
: UnsafeMutablePointer(b.start) - x.startASCII
? b.start - UnsafeMutableRawPointer(x.startUTF16)
: b.start - UnsafeMutableRawPointer(x.startASCII)
return "Contiguous(owner: "
+ "\(hexAddr(x._owner))[\(offset)...\(x.count + offset)]"
+ ", capacity = \(b.capacity))"