mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -35,7 +35,7 @@ vectorElementNames = [
|
|||||||
public func _indexHomogeneousValue<TTT, T>(_ aggregate: UnsafePointer<TTT>,
|
public func _indexHomogeneousValue<TTT, T>(_ aggregate: UnsafePointer<TTT>,
|
||||||
_ index: Int) -> T {
|
_ index: Int) -> T {
|
||||||
return UnsafeRawPointer(aggregate).load(
|
return UnsafeRawPointer(aggregate).load(
|
||||||
fromByteOffset: index * strideof(T), as: T.self)
|
fromByteOffset: index * strideof(T.self), as: T.self)
|
||||||
}
|
}
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ public struct Character :
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if let native = s._core.nativeBuffer,
|
if let native = s._core.nativeBuffer,
|
||||||
native.start == UnsafeMutablePointer(s._core._baseAddress!) {
|
native.start == s._core._baseAddress! {
|
||||||
_representation = .large(native._storage)
|
_representation = .large(native._storage)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,19 +20,21 @@ import SwiftShims
|
|||||||
// Atomics
|
// Atomics
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
public typealias _PointerToPointer = UnsafeMutablePointer<UnsafeRawPointer?>
|
||||||
|
|
||||||
@_transparent
|
@_transparent
|
||||||
public // @testable
|
public // @testable
|
||||||
func _stdlib_atomicCompareExchangeStrongPtrImpl(
|
func _stdlib_atomicCompareExchangeStrongPtr(
|
||||||
object target: UnsafeMutablePointer<UnsafeMutableRawPointer?>,
|
object target: _PointerToPointer,
|
||||||
expected: UnsafeMutablePointer<UnsafeMutableRawPointer?>,
|
expected: _PointerToPointer,
|
||||||
desired: UnsafeMutableRawPointer?) -> Bool {
|
desired: UnsafeRawPointer?) -> Bool {
|
||||||
|
|
||||||
// We use Builtin.Word here because Builtin.RawPointer can't be nil.
|
// We use Builtin.Word here because Builtin.RawPointer can't be nil.
|
||||||
let (oldValue, won) = Builtin.cmpxchg_seqcst_seqcst_Word(
|
let (oldValue, won) = Builtin.cmpxchg_seqcst_seqcst_Word(
|
||||||
target._rawValue,
|
target._rawValue,
|
||||||
UInt(bitPattern: expected.pointee)._builtinWordValue,
|
UInt(bitPattern: expected.pointee)._builtinWordValue,
|
||||||
UInt(bitPattern: desired)._builtinWordValue)
|
UInt(bitPattern: desired)._builtinWordValue)
|
||||||
expected.pointee = UnsafeMutableRawPointer(bitPattern: Int(oldValue))
|
expected.pointee = UnsafeRawPointer(bitPattern: Int(oldValue))
|
||||||
return Bool(won)
|
return Bool(won)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,12 +72,12 @@ func _stdlib_atomicCompareExchangeStrongPtr<T>(
|
|||||||
object target: UnsafeMutablePointer<UnsafeMutablePointer<T>${optional}>,
|
object target: UnsafeMutablePointer<UnsafeMutablePointer<T>${optional}>,
|
||||||
expected: UnsafeMutablePointer<UnsafeMutablePointer<T>${optional}>,
|
expected: UnsafeMutablePointer<UnsafeMutablePointer<T>${optional}>,
|
||||||
desired: UnsafeMutablePointer<T>${optional}) -> Bool {
|
desired: UnsafeMutablePointer<T>${optional}) -> Bool {
|
||||||
return _stdlib_atomicCompareExchangeStrongPtrImpl(
|
return _stdlib_atomicCompareExchangeStrongPtr(
|
||||||
object: UnsafeMutablePointer(target),
|
object: unsafeBitCast(target, to: _PointerToPointer.self),
|
||||||
expected: UnsafeMutablePointer(expected),
|
expected: unsafeBitCast(expected, to: _PointerToPointer.self),
|
||||||
desired: UnsafeMutablePointer(desired))
|
desired: unsafeBitCast(desired, to: Optional<UnsafeRawPointer>.self))
|
||||||
}
|
}
|
||||||
% end
|
% end # optional
|
||||||
|
|
||||||
@_transparent
|
@_transparent
|
||||||
@discardableResult
|
@discardableResult
|
||||||
@@ -83,10 +85,10 @@ public // @testable
|
|||||||
func _stdlib_atomicInitializeARCRef(
|
func _stdlib_atomicInitializeARCRef(
|
||||||
object target: UnsafeMutablePointer<AnyObject?>,
|
object target: UnsafeMutablePointer<AnyObject?>,
|
||||||
desired: AnyObject) -> Bool {
|
desired: AnyObject) -> Bool {
|
||||||
var expected: UnsafeMutableRawPointer? = nil
|
var expected: UnsafeRawPointer? = nil
|
||||||
let desiredPtr = Unmanaged.passRetained(desired).toOpaque()
|
let desiredPtr = Unmanaged.passRetained(desired).toOpaque()
|
||||||
let wonRace = _stdlib_atomicCompareExchangeStrongPtrImpl(
|
let wonRace = _stdlib_atomicCompareExchangeStrongPtr(
|
||||||
object: UnsafeMutablePointer(target),
|
object: unsafeBitCast(target, to: _PointerToPointer.self),
|
||||||
expected: &expected,
|
expected: &expected,
|
||||||
desired: desiredPtr)
|
desired: desiredPtr)
|
||||||
if !wonRace {
|
if !wonRace {
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ extension String : _ExpressibleByBuiltinUTF16StringLiteral {
|
|||||||
) {
|
) {
|
||||||
self = String(
|
self = String(
|
||||||
_StringCore(
|
_StringCore(
|
||||||
baseAddress: OpaquePointer(start),
|
baseAddress: UnsafeMutableRawPointer(start),
|
||||||
count: Int(utf16CodeUnitCount),
|
count: Int(utf16CodeUnitCount),
|
||||||
elementShift: 1,
|
elementShift: 1,
|
||||||
hasCocoaBuffer: false,
|
hasCocoaBuffer: false,
|
||||||
@@ -418,7 +418,7 @@ extension String : _ExpressibleByBuiltinStringLiteral {
|
|||||||
if Bool(isASCII) {
|
if Bool(isASCII) {
|
||||||
self = String(
|
self = String(
|
||||||
_StringCore(
|
_StringCore(
|
||||||
baseAddress: OpaquePointer(start),
|
baseAddress: UnsafeMutableRawPointer(start),
|
||||||
count: Int(utf8CodeUnitCount),
|
count: Int(utf8CodeUnitCount),
|
||||||
elementShift: 0,
|
elementShift: 0,
|
||||||
hasCocoaBuffer: false,
|
hasCocoaBuffer: false,
|
||||||
@@ -699,13 +699,15 @@ extension String : Hashable {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if self._core.isASCII {
|
if self._core.isASCII {
|
||||||
return _swift_stdlib_unicode_hash_ascii(
|
return _core.startASCII.withMemoryRebound(
|
||||||
UnsafeMutablePointer<Int8>(_core.startASCII),
|
to: CChar.self, capacity: _core.count) {
|
||||||
Int32(_core.count))
|
_swift_stdlib_unicode_hash_ascii($0, Int32(_core.count))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return _swift_stdlib_unicode_hash(
|
return _core.startUTF16.withMemoryRebound(
|
||||||
UnsafeMutablePointer<UInt16>(_core.startUTF16),
|
to: UInt16.self, capacity: _core.count) {
|
||||||
Int32(_core.count))
|
_swift_stdlib_unicode_hash($0, Int32(_core.count))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -821,7 +823,8 @@ internal func _nativeUnicodeLowercaseString(_ str: String) -> String {
|
|||||||
capacity: str._core.count, initialSize: str._core.count, elementWidth: 2)
|
capacity: str._core.count, initialSize: str._core.count, elementWidth: 2)
|
||||||
|
|
||||||
// Try to write it out to the same length.
|
// 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(
|
let z = _swift_stdlib_unicode_strToLower(
|
||||||
dest, Int32(str._core.count),
|
dest, Int32(str._core.count),
|
||||||
str._core.startUTF16, 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 {
|
if correctSize != str._core.count {
|
||||||
buffer = _StringBuffer(
|
buffer = _StringBuffer(
|
||||||
capacity: correctSize, initialSize: correctSize, elementWidth: 2)
|
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(
|
_swift_stdlib_unicode_strToLower(
|
||||||
dest, Int32(correctSize), str._core.startUTF16, Int32(str._core.count))
|
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)
|
capacity: str._core.count, initialSize: str._core.count, elementWidth: 2)
|
||||||
|
|
||||||
// Try to write it out to the same length.
|
// 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(
|
let z = _swift_stdlib_unicode_strToUpper(
|
||||||
dest, Int32(str._core.count),
|
dest, Int32(str._core.count),
|
||||||
str._core.startUTF16, 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 {
|
if correctSize != str._core.count {
|
||||||
buffer = _StringBuffer(
|
buffer = _StringBuffer(
|
||||||
capacity: correctSize, initialSize: correctSize, elementWidth: 2)
|
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(
|
_swift_stdlib_unicode_strToUpper(
|
||||||
dest, Int32(correctSize), str._core.startUTF16, Int32(str._core.count))
|
dest, Int32(correctSize), str._core.startUTF16, Int32(str._core.count))
|
||||||
}
|
}
|
||||||
@@ -904,7 +910,7 @@ extension String {
|
|||||||
let source = self._core.startASCII
|
let source = self._core.startASCII
|
||||||
let buffer = _StringBuffer(
|
let buffer = _StringBuffer(
|
||||||
capacity: count, initialSize: count, elementWidth: 1)
|
capacity: count, initialSize: count, elementWidth: 1)
|
||||||
let dest = UnsafeMutablePointer<UInt8>(buffer.start)
|
let dest = buffer.start
|
||||||
for i in 0..<count {
|
for i in 0..<count {
|
||||||
// For each character in the string, we lookup if it should be shifted
|
// 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.
|
// 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
|
// 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
|
// a UInt8 and add to our ASCII value (this will not overflow numbers in
|
||||||
// the ASCII range).
|
// 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)
|
return String(_storage: buffer)
|
||||||
}
|
}
|
||||||
@@ -953,7 +960,7 @@ extension String {
|
|||||||
let source = self._core.startASCII
|
let source = self._core.startASCII
|
||||||
let buffer = _StringBuffer(
|
let buffer = _StringBuffer(
|
||||||
capacity: count, initialSize: count, elementWidth: 1)
|
capacity: count, initialSize: count, elementWidth: 1)
|
||||||
let dest = UnsafeMutablePointer<UInt8>(buffer.start)
|
let dest = buffer.start
|
||||||
for i in 0..<count {
|
for i in 0..<count {
|
||||||
// See the comment above in lowercaseString.
|
// See the comment above in lowercaseString.
|
||||||
let value = source[i]
|
let value = source[i]
|
||||||
@@ -961,7 +968,8 @@ extension String {
|
|||||||
_asciiLowerCaseTable >>
|
_asciiLowerCaseTable >>
|
||||||
UInt64(((value &- 1) & 0b0111_1111) >> 1)
|
UInt64(((value &- 1) & 0b0111_1111) >> 1)
|
||||||
let add = (isLower & 0x1) << 5
|
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)
|
return String(_storage: buffer)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ func _cocoaStringToSwiftString_NonASCII(
|
|||||||
let start = _stdlib_binary_CFStringGetCharactersPtr(cfImmutableValue)
|
let start = _stdlib_binary_CFStringGetCharactersPtr(cfImmutableValue)
|
||||||
|
|
||||||
return String(_StringCore(
|
return String(_StringCore(
|
||||||
baseAddress: OpaquePointer(start),
|
baseAddress: start,
|
||||||
count: length,
|
count: length,
|
||||||
elementShift: 1,
|
elementShift: 1,
|
||||||
hasCocoaBuffer: true,
|
hasCocoaBuffer: true,
|
||||||
@@ -81,7 +81,7 @@ internal func _cocoaStringToContiguous(
|
|||||||
|
|
||||||
_swift_stdlib_CFStringGetCharacters(
|
_swift_stdlib_CFStringGetCharacters(
|
||||||
source, _swift_shims_CFRange(location: startIndex, length: count),
|
source, _swift_shims_CFRange(location: startIndex, length: count),
|
||||||
UnsafeMutablePointer<_swift_shims_UniChar>(buffer.start))
|
buffer.start.assumingMemoryBound(to: _swift_shims_UniChar.self))
|
||||||
|
|
||||||
return buffer
|
return buffer
|
||||||
}
|
}
|
||||||
@@ -163,13 +163,13 @@ extension String {
|
|||||||
|
|
||||||
// start will hold the base pointer of contiguous storage, if it
|
// start will hold the base pointer of contiguous storage, if it
|
||||||
// is found.
|
// is found.
|
||||||
var start: OpaquePointer?
|
var start: UnsafeMutableRawPointer?
|
||||||
let isUTF16 = (nulTerminatedASCII == nil)
|
let isUTF16 = (nulTerminatedASCII == nil)
|
||||||
if isUTF16 {
|
if isUTF16 {
|
||||||
let utf16Buf = _swift_stdlib_CFStringGetCharactersPtr(cfImmutableValue)
|
let utf16Buf = _swift_stdlib_CFStringGetCharactersPtr(cfImmutableValue)
|
||||||
start = OpaquePointer(utf16Buf)
|
start = UnsafeMutableRawPointer(mutating: utf16Buf)
|
||||||
} else {
|
} else {
|
||||||
start = OpaquePointer(nulTerminatedASCII)
|
start = UnsafeMutableRawPointer(mutating: nulTerminatedASCII)
|
||||||
}
|
}
|
||||||
|
|
||||||
self._core = _StringCore(
|
self._core = _StringCore(
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ struct _StringBufferIVars {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal init(
|
internal init(
|
||||||
_usedEnd: UnsafeMutablePointer<_RawByte>,
|
_usedEnd: UnsafeMutableRawPointer,
|
||||||
byteCapacity: Int,
|
byteCapacity: Int,
|
||||||
elementWidth: Int
|
elementWidth: Int
|
||||||
) {
|
) {
|
||||||
@@ -31,7 +31,7 @@ struct _StringBufferIVars {
|
|||||||
|
|
||||||
// This stored property should be stored at offset zero. We perform atomic
|
// This stored property should be stored at offset zero. We perform atomic
|
||||||
// operations on it using _HeapBuffer's pointer.
|
// operations on it using _HeapBuffer's pointer.
|
||||||
var usedEnd: UnsafeMutablePointer<_RawByte>?
|
var usedEnd: UnsafeMutableRawPointer?
|
||||||
|
|
||||||
var capacityAndElementShift: Int
|
var capacityAndElementShift: Int
|
||||||
var byteCapacity: Int {
|
var byteCapacity: Int {
|
||||||
@@ -78,6 +78,14 @@ public struct _StringBuffer {
|
|||||||
_StringBufferIVars(_elementWidth: elementWidth),
|
_StringBufferIVars(_elementWidth: elementWidth),
|
||||||
(capacity + capacityBump + divRound) >> divRound
|
(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)
|
self.usedEnd = start + (initialSize << elementShift)
|
||||||
_storage.value.capacityAndElementShift
|
_storage.value.capacityAndElementShift
|
||||||
= ((_storage._capacity() - capacityBump) << 1) + elementShift
|
= ((_storage._capacity() - capacityBump) << 1) + elementShift
|
||||||
@@ -107,7 +115,7 @@ public struct _StringBuffer {
|
|||||||
elementWidth: isAscii ? 1 : 2)
|
elementWidth: isAscii ? 1 : 2)
|
||||||
|
|
||||||
if isAscii {
|
if isAscii {
|
||||||
var p = UnsafeMutablePointer<UTF8.CodeUnit>(result.start)
|
var p = result.start.assumingMemoryBound(to: UTF8.CodeUnit.self)
|
||||||
let sink: (UTF32.CodeUnit) -> Void = {
|
let sink: (UTF32.CodeUnit) -> Void = {
|
||||||
p.pointee = UTF8.CodeUnit($0)
|
p.pointee = UTF8.CodeUnit($0)
|
||||||
p += 1
|
p += 1
|
||||||
@@ -137,12 +145,12 @@ public struct _StringBuffer {
|
|||||||
|
|
||||||
/// A pointer to the start of this buffer's data area.
|
/// A pointer to the start of this buffer's data area.
|
||||||
public // @testable
|
public // @testable
|
||||||
var start: UnsafeMutablePointer<_RawByte> {
|
var start: UnsafeMutableRawPointer {
|
||||||
return UnsafeMutablePointer(_storage.baseAddress)
|
return UnsafeMutableRawPointer(_storage.baseAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A past-the-end pointer for this buffer's stored data.
|
/// A past-the-end pointer for this buffer's stored data.
|
||||||
var usedEnd: UnsafeMutablePointer<_RawByte> {
|
var usedEnd: UnsafeMutableRawPointer {
|
||||||
get {
|
get {
|
||||||
return _storage.value.usedEnd!
|
return _storage.value.usedEnd!
|
||||||
}
|
}
|
||||||
@@ -156,7 +164,7 @@ public struct _StringBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A past-the-end pointer for this buffer's available storage.
|
/// A past-the-end pointer for this buffer's available storage.
|
||||||
var capacityEnd: UnsafeMutablePointer<_RawByte> {
|
var capacityEnd: UnsafeMutableRawPointer {
|
||||||
return start + _storage.value.byteCapacity
|
return start + _storage.value.byteCapacity
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,11 +189,11 @@ public struct _StringBuffer {
|
|||||||
// two separate phases. Operations with one-phase growth should use
|
// two separate phases. Operations with one-phase growth should use
|
||||||
// "grow()," below.
|
// "grow()," below.
|
||||||
func hasCapacity(
|
func hasCapacity(
|
||||||
_ cap: Int, forSubRange r: Range<UnsafePointer<_RawByte>>
|
_ cap: Int, forSubRange r: Range<UnsafeRawPointer>
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
// The substring to be grown could be pointing in the middle of this
|
// The substring to be grown could be pointing in the middle of this
|
||||||
// _StringBuffer.
|
// _StringBuffer.
|
||||||
let offset = (r.lowerBound - UnsafePointer(start)) >> elementShift
|
let offset = (r.lowerBound - UnsafeRawPointer(start)) >> elementShift
|
||||||
return cap + offset <= capacity
|
return cap + offset <= capacity
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,13 +210,14 @@ public struct _StringBuffer {
|
|||||||
@inline(__always)
|
@inline(__always)
|
||||||
@discardableResult
|
@discardableResult
|
||||||
mutating func grow(
|
mutating func grow(
|
||||||
oldBounds bounds: Range<UnsafePointer<_RawByte>>, newUsedCount: Int
|
oldBounds bounds: Range<UnsafeRawPointer>, newUsedCount: Int
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
var newUsedCount = newUsedCount
|
var newUsedCount = newUsedCount
|
||||||
// The substring to be grown could be pointing in the middle of this
|
// The substring to be grown could be pointing in the middle of this
|
||||||
// _StringBuffer. Adjust the size so that it covers the imaginary
|
// _StringBuffer. Adjust the size so that it covers the imaginary
|
||||||
// substring from the start of the buffer to `oldUsedEnd`.
|
// 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) {
|
if _slowPath(newUsedCount > capacity) {
|
||||||
return false
|
return false
|
||||||
@@ -230,11 +239,14 @@ public struct _StringBuffer {
|
|||||||
// usedEnd = newUsedEnd
|
// usedEnd = newUsedEnd
|
||||||
// return true
|
// return true
|
||||||
// }
|
// }
|
||||||
let usedEndPhysicalPtr =
|
|
||||||
UnsafeMutablePointer<UnsafeMutablePointer<_RawByte>>(_storage._value)
|
// &StringBufferIVars.usedEnd
|
||||||
var expected = UnsafeMutablePointer<_RawByte>(bounds.upperBound)
|
let usedEndPhysicalPtr = _PointerToPointer(_storage._value)
|
||||||
|
// Create a temp var to hold the exchanged `expected` value.
|
||||||
|
var expected : UnsafeRawPointer? = bounds.upperBound
|
||||||
if _stdlib_atomicCompareExchangeStrongPtr(
|
if _stdlib_atomicCompareExchangeStrongPtr(
|
||||||
object: usedEndPhysicalPtr, expected: &expected, desired: newUsedEnd) {
|
object: usedEndPhysicalPtr, expected: &expected,
|
||||||
|
desired: UnsafeRawPointer(newUsedEnd)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,13 +28,13 @@
|
|||||||
public struct _StringCore {
|
public struct _StringCore {
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Internals
|
// Internals
|
||||||
public var _baseAddress: OpaquePointer?
|
public var _baseAddress: UnsafeMutableRawPointer?
|
||||||
var _countAndFlags: UInt
|
var _countAndFlags: UInt
|
||||||
public var _owner: AnyObject?
|
public var _owner: AnyObject?
|
||||||
|
|
||||||
/// (private) create the implementation of a string from its component parts.
|
/// (private) create the implementation of a string from its component parts.
|
||||||
init(
|
init(
|
||||||
baseAddress: OpaquePointer?,
|
baseAddress: UnsafeMutableRawPointer?,
|
||||||
_countAndFlags: UInt,
|
_countAndFlags: UInt,
|
||||||
owner: AnyObject?
|
owner: AnyObject?
|
||||||
) {
|
) {
|
||||||
@@ -68,10 +68,9 @@ public struct _StringCore {
|
|||||||
_sanityCheck(!hasCocoaBuffer)
|
_sanityCheck(!hasCocoaBuffer)
|
||||||
_sanityCheck(elementWidth == buffer.elementWidth,
|
_sanityCheck(elementWidth == buffer.elementWidth,
|
||||||
"_StringCore elementWidth doesn't match its buffer's")
|
"_StringCore elementWidth doesn't match its buffer's")
|
||||||
_sanityCheck(UnsafeMutablePointer(_baseAddress!) >= buffer.start)
|
_sanityCheck(_baseAddress! >= buffer.start)
|
||||||
_sanityCheck(UnsafeMutablePointer(_baseAddress!) <= buffer.usedEnd)
|
_sanityCheck(_baseAddress! <= buffer.usedEnd)
|
||||||
_sanityCheck(
|
_sanityCheck(_pointer(toElementAt: count) <= buffer.usedEnd)
|
||||||
UnsafeMutablePointer(_pointer(toElementAt: count)) <= buffer.usedEnd)
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -97,29 +96,28 @@ public struct _StringCore {
|
|||||||
/// storage. Caveats: The string must have contiguous storage; the
|
/// storage. Caveats: The string must have contiguous storage; the
|
||||||
/// element may be 1 or 2 bytes wide, depending on elementWidth; the
|
/// element may be 1 or 2 bytes wide, depending on elementWidth; the
|
||||||
/// result may be null if the string is empty.
|
/// 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)
|
_sanityCheck(hasContiguousStorage && n >= 0 && n <= count)
|
||||||
return OpaquePointer(
|
return _baseAddress! + (n << elementShift)
|
||||||
UnsafeMutablePointer<_RawByte>(_baseAddress!) + (n << elementShift))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static func _copyElements(
|
static func _copyElements(
|
||||||
_ srcStart: OpaquePointer, srcElementWidth: Int,
|
_ srcStart: UnsafeMutableRawPointer, srcElementWidth: Int,
|
||||||
dstStart: OpaquePointer, dstElementWidth: Int,
|
dstStart: UnsafeMutableRawPointer, dstElementWidth: Int,
|
||||||
count: Int
|
count: Int
|
||||||
) {
|
) {
|
||||||
// Copy the old stuff into the new storage
|
// Copy the old stuff into the new storage
|
||||||
if _fastPath(srcElementWidth == dstElementWidth) {
|
if _fastPath(srcElementWidth == dstElementWidth) {
|
||||||
// No change in storage width; we can use memcpy
|
// No change in storage width; we can use memcpy
|
||||||
_memcpy(
|
_memcpy(
|
||||||
dest: UnsafeMutablePointer(dstStart),
|
dest: dstStart,
|
||||||
src: UnsafeMutablePointer(srcStart),
|
src: srcStart,
|
||||||
size: UInt(count << (srcElementWidth - 1)))
|
size: UInt(count << (srcElementWidth - 1)))
|
||||||
}
|
}
|
||||||
else if (srcElementWidth < dstElementWidth) {
|
else if (srcElementWidth < dstElementWidth) {
|
||||||
// Widening ASCII to UTF-16; we need to copy the bytes manually
|
// Widening ASCII to UTF-16; we need to copy the bytes manually
|
||||||
var dest = UnsafeMutablePointer<UTF16.CodeUnit>(dstStart)
|
var dest = dstStart.assumingMemoryBound(to: UTF16.CodeUnit.self)
|
||||||
var src = UnsafeMutablePointer<UTF8.CodeUnit>(srcStart)
|
var src = srcStart.assumingMemoryBound(to: UTF8.CodeUnit.self)
|
||||||
let srcEnd = src + count
|
let srcEnd = src + count
|
||||||
while (src != srcEnd) {
|
while (src != srcEnd) {
|
||||||
dest.pointee = UTF16.CodeUnit(src.pointee)
|
dest.pointee = UTF16.CodeUnit(src.pointee)
|
||||||
@@ -129,8 +127,8 @@ public struct _StringCore {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Narrowing UTF-16 to ASCII; we need to copy the bytes manually
|
// Narrowing UTF-16 to ASCII; we need to copy the bytes manually
|
||||||
var dest = UnsafeMutablePointer<UTF8.CodeUnit>(dstStart)
|
var dest = dstStart.assumingMemoryBound(to: UTF8.CodeUnit.self)
|
||||||
var src = UnsafeMutablePointer<UTF16.CodeUnit>(srcStart)
|
var src = srcStart.assumingMemoryBound(to: UTF16.CodeUnit.self)
|
||||||
let srcEnd = src + count
|
let srcEnd = src + count
|
||||||
while (src != srcEnd) {
|
while (src != srcEnd) {
|
||||||
dest.pointee = UTF8.CodeUnit(src.pointee)
|
dest.pointee = UTF8.CodeUnit(src.pointee)
|
||||||
@@ -143,7 +141,7 @@ public struct _StringCore {
|
|||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Initialization
|
// Initialization
|
||||||
public init(
|
public init(
|
||||||
baseAddress: OpaquePointer?,
|
baseAddress: UnsafeMutableRawPointer?,
|
||||||
count: Int,
|
count: Int,
|
||||||
elementShift: Int,
|
elementShift: Int,
|
||||||
hasCocoaBuffer: Bool,
|
hasCocoaBuffer: Bool,
|
||||||
@@ -165,7 +163,7 @@ public struct _StringCore {
|
|||||||
/// Create a _StringCore that covers the entire length of the _StringBuffer.
|
/// Create a _StringCore that covers the entire length of the _StringBuffer.
|
||||||
init(_ buffer: _StringBuffer) {
|
init(_ buffer: _StringBuffer) {
|
||||||
self = _StringCore(
|
self = _StringCore(
|
||||||
baseAddress: OpaquePointer(buffer.start),
|
baseAddress: buffer.start,
|
||||||
count: buffer.usedCount,
|
count: buffer.usedCount,
|
||||||
elementShift: buffer.elementShift,
|
elementShift: buffer.elementShift,
|
||||||
hasCocoaBuffer: false,
|
hasCocoaBuffer: false,
|
||||||
@@ -199,7 +197,7 @@ public struct _StringCore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Left shift amount to apply to an offset N so that when
|
/// 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 {
|
var elementShift: Int {
|
||||||
return Int(_countAndFlags >> (UInt._sizeInBits - 1))
|
return Int(_countAndFlags >> (UInt._sizeInBits - 1))
|
||||||
}
|
}
|
||||||
@@ -227,7 +225,7 @@ public struct _StringCore {
|
|||||||
|
|
||||||
public var startASCII: UnsafeMutablePointer<UTF8.CodeUnit> {
|
public var startASCII: UnsafeMutablePointer<UTF8.CodeUnit> {
|
||||||
_sanityCheck(elementWidth == 1, "String does not contain contiguous ASCII")
|
_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.
|
/// True iff a contiguous ASCII buffer available.
|
||||||
@@ -239,7 +237,7 @@ public struct _StringCore {
|
|||||||
_sanityCheck(
|
_sanityCheck(
|
||||||
count == 0 || elementWidth == 2,
|
count == 0 || elementWidth == 2,
|
||||||
"String does not contain contiguous UTF-16")
|
"String does not contain contiguous UTF-16")
|
||||||
return UnsafeMutablePointer(_baseAddress!)
|
return _baseAddress!.assumingMemoryBound(to: UTF16.CodeUnit.self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// the native _StringBuffer, if any, or `nil`.
|
/// the native _StringBuffer, if any, or `nil`.
|
||||||
@@ -336,7 +334,7 @@ public struct _StringCore {
|
|||||||
if _fastPath(_baseAddress != nil) {
|
if _fastPath(_baseAddress != nil) {
|
||||||
if _fastPath(elementWidth == 1) {
|
if _fastPath(elementWidth == 1) {
|
||||||
for x in UnsafeBufferPointer(
|
for x in UnsafeBufferPointer(
|
||||||
start: UnsafeMutablePointer<UTF8.CodeUnit>(_baseAddress!),
|
start: _baseAddress!.assumingMemoryBound(to: UTF8.CodeUnit.self),
|
||||||
count: count
|
count: count
|
||||||
) {
|
) {
|
||||||
Encoding.encode(UnicodeScalar(x), into: processCodeUnit)
|
Encoding.encode(UnicodeScalar(x), into: processCodeUnit)
|
||||||
@@ -345,7 +343,7 @@ public struct _StringCore {
|
|||||||
else {
|
else {
|
||||||
let hadError = transcode(
|
let hadError = transcode(
|
||||||
UnsafeBufferPointer(
|
UnsafeBufferPointer(
|
||||||
start: UnsafeMutablePointer<UTF16.CodeUnit>(_baseAddress!),
|
start: _baseAddress!.assumingMemoryBound(to: UTF16.CodeUnit.self),
|
||||||
count: count
|
count: count
|
||||||
).makeIterator(),
|
).makeIterator(),
|
||||||
from: UTF16.self,
|
from: UTF16.self,
|
||||||
@@ -381,7 +379,7 @@ public struct _StringCore {
|
|||||||
/// existing buffer, the suggested new capacity will at least double
|
/// existing buffer, the suggested new capacity will at least double
|
||||||
/// the existing buffer's storage.
|
/// the existing buffer's storage.
|
||||||
mutating func _claimCapacity(
|
mutating func _claimCapacity(
|
||||||
_ newSize: Int, minElementWidth: Int) -> (Int, OpaquePointer?) {
|
_ newSize: Int, minElementWidth: Int) -> (Int, UnsafeMutableRawPointer?) {
|
||||||
if _fastPath((nativeBuffer != nil) && elementWidth >= minElementWidth) {
|
if _fastPath((nativeBuffer != nil) && elementWidth >= minElementWidth) {
|
||||||
var buffer = nativeBuffer!
|
var buffer = nativeBuffer!
|
||||||
|
|
||||||
@@ -394,7 +392,7 @@ public struct _StringCore {
|
|||||||
// Attempt to claim unused capacity in the buffer
|
// Attempt to claim unused capacity in the buffer
|
||||||
if _fastPath(
|
if _fastPath(
|
||||||
buffer.grow(
|
buffer.grow(
|
||||||
oldBounds: UnsafePointer(usedStart)..<UnsafePointer(usedEnd),
|
oldBounds: UnsafeRawPointer(usedStart)..<UnsafeRawPointer(usedEnd),
|
||||||
newUsedCount: newSize)
|
newUsedCount: newSize)
|
||||||
) {
|
) {
|
||||||
count = newSize
|
count = newSize
|
||||||
@@ -415,7 +413,7 @@ public struct _StringCore {
|
|||||||
/// you must immediately copy valid data into that storage.
|
/// you must immediately copy valid data into that storage.
|
||||||
mutating func _growBuffer(
|
mutating func _growBuffer(
|
||||||
_ newSize: Int, minElementWidth: Int
|
_ newSize: Int, minElementWidth: Int
|
||||||
) -> OpaquePointer {
|
) -> UnsafeMutableRawPointer {
|
||||||
let (newCapacity, existingStorage)
|
let (newCapacity, existingStorage)
|
||||||
= _claimCapacity(newSize, minElementWidth: minElementWidth)
|
= _claimCapacity(newSize, minElementWidth: minElementWidth)
|
||||||
|
|
||||||
@@ -455,7 +453,7 @@ public struct _StringCore {
|
|||||||
if hasContiguousStorage {
|
if hasContiguousStorage {
|
||||||
_StringCore._copyElements(
|
_StringCore._copyElements(
|
||||||
_baseAddress!, srcElementWidth: elementWidth,
|
_baseAddress!, srcElementWidth: elementWidth,
|
||||||
dstStart: OpaquePointer(newStorage.start),
|
dstStart: UnsafeMutableRawPointer(newStorage.start),
|
||||||
dstElementWidth: newElementWidth, count: oldCount)
|
dstElementWidth: newElementWidth, count: oldCount)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -465,7 +463,8 @@ public struct _StringCore {
|
|||||||
// FIXME: can we get Cocoa to tell us quickly that an opaque
|
// FIXME: can we get Cocoa to tell us quickly that an opaque
|
||||||
// string is ASCII? Do we care much about that edge case?
|
// string is ASCII? Do we care much about that edge case?
|
||||||
_sanityCheck(newStorage.elementShift == 1)
|
_sanityCheck(newStorage.elementShift == 1)
|
||||||
_cocoaStringReadAll(cocoaBuffer!, UnsafeMutablePointer(newStorage.start))
|
_cocoaStringReadAll(cocoaBuffer!,
|
||||||
|
newStorage.start.assumingMemoryBound(to: UTF16.CodeUnit.self))
|
||||||
#else
|
#else
|
||||||
_sanityCheckFailure("_copyInPlace: non-native string without objc runtime")
|
_sanityCheckFailure("_copyInPlace: non-native string without objc runtime")
|
||||||
#endif
|
#endif
|
||||||
@@ -502,15 +501,14 @@ public struct _StringCore {
|
|||||||
count + utf16Width, minElementWidth: minBytesPerCodeUnit)
|
count + utf16Width, minElementWidth: minBytesPerCodeUnit)
|
||||||
|
|
||||||
if _fastPath(elementWidth == 1) {
|
if _fastPath(elementWidth == 1) {
|
||||||
_sanityCheck(
|
_sanityCheck(_pointer(toElementAt:count) == destination + 1)
|
||||||
_pointer(toElementAt:count)
|
|
||||||
== OpaquePointer(UnsafeMutablePointer<_RawByte>(destination) + 1))
|
|
||||||
|
|
||||||
UnsafeMutablePointer<UTF8.CodeUnit>(destination)[0] = UTF8.CodeUnit(u0)
|
destination.assumingMemoryBound(to: UTF8.CodeUnit.self)[0]
|
||||||
|
= UTF8.CodeUnit(u0)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let destination16
|
let destination16
|
||||||
= UnsafeMutablePointer<UTF16.CodeUnit>(destination._rawValue)
|
= destination.assumingMemoryBound(to: UTF16.CodeUnit.self)
|
||||||
|
|
||||||
destination16[0] = u0
|
destination16[0] = u0
|
||||||
if u1 != nil {
|
if u1 != nil {
|
||||||
@@ -539,7 +537,8 @@ public struct _StringCore {
|
|||||||
else {
|
else {
|
||||||
#if _runtime(_ObjC)
|
#if _runtime(_ObjC)
|
||||||
_sanityCheck(elementWidth == 2)
|
_sanityCheck(elementWidth == 2)
|
||||||
_cocoaStringReadAll(rhs.cocoaBuffer!, UnsafeMutablePointer(destination))
|
_cocoaStringReadAll(rhs.cocoaBuffer!,
|
||||||
|
destination.assumingMemoryBound(to: UTF16.CodeUnit.self))
|
||||||
#else
|
#else
|
||||||
_sanityCheckFailure("subscript: non-native string without objc runtime")
|
_sanityCheckFailure("subscript: non-native string without objc runtime")
|
||||||
#endif
|
#endif
|
||||||
@@ -560,7 +559,7 @@ public struct _StringCore {
|
|||||||
}
|
}
|
||||||
let unsafeBuffer =
|
let unsafeBuffer =
|
||||||
UnsafeBufferPointer(
|
UnsafeBufferPointer(
|
||||||
start: UnsafeMutablePointer<UTF16.CodeUnit>(_baseAddress),
|
start: _baseAddress!.assumingMemoryBound(to: UTF16.CodeUnit.self),
|
||||||
count: count)
|
count: count)
|
||||||
return !unsafeBuffer.contains { $0 > 0x7f }
|
return !unsafeBuffer.contains { $0 > 0x7f }
|
||||||
}
|
}
|
||||||
@@ -618,24 +617,23 @@ extension _StringCore : RangeReplaceableCollection {
|
|||||||
) ? _claimCapacity(newCount, minElementWidth: width).1 : nil
|
) ? _claimCapacity(newCount, minElementWidth: width).1 : nil
|
||||||
|
|
||||||
if _fastPath(existingStorage != nil) {
|
if _fastPath(existingStorage != nil) {
|
||||||
let rangeStart = UnsafeMutablePointer<UInt8>(
|
let rangeStart = _pointer(toElementAt:bounds.lowerBound)
|
||||||
_pointer(toElementAt:bounds.lowerBound))
|
|
||||||
let tailStart = rangeStart + (replacedCount << elementShift)
|
let tailStart = rangeStart + (replacedCount << elementShift)
|
||||||
|
|
||||||
if growth > 0 {
|
if growth > 0 {
|
||||||
(tailStart + (growth << elementShift)).assign(
|
(tailStart + (growth << elementShift)).copyBytes(
|
||||||
from: tailStart, count: tailCount << elementShift)
|
from: tailStart, count: tailCount << elementShift)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _fastPath(elementWidth == 1) {
|
if _fastPath(elementWidth == 1) {
|
||||||
var dst = rangeStart
|
var dst = rangeStart.assumingMemoryBound(to: UTF8.CodeUnit.self)
|
||||||
for u in newElements {
|
for u in newElements {
|
||||||
dst.pointee = UInt8(truncatingBitPattern: u)
|
dst.pointee = UInt8(truncatingBitPattern: u)
|
||||||
dst += 1
|
dst += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var dst = UnsafeMutablePointer<UTF16.CodeUnit>(rangeStart)
|
var dst = rangeStart.assumingMemoryBound(to: UTF16.CodeUnit.self)
|
||||||
for u in newElements {
|
for u in newElements {
|
||||||
dst.pointee = u
|
dst.pointee = u
|
||||||
dst += 1
|
dst += 1
|
||||||
@@ -643,7 +641,7 @@ extension _StringCore : RangeReplaceableCollection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if growth < 0 {
|
if growth < 0 {
|
||||||
(tailStart + (growth << elementShift)).assign(
|
(tailStart + (growth << elementShift)).copyBytes(
|
||||||
from: tailStart, count: tailCount << elementShift)
|
from: tailStart, count: tailCount << elementShift)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -668,8 +666,9 @@ extension _StringCore : RangeReplaceableCollection {
|
|||||||
if _fastPath(!hasCocoaBuffer) {
|
if _fastPath(!hasCocoaBuffer) {
|
||||||
if _fastPath(isKnownUniquelyReferenced(&_owner)) {
|
if _fastPath(isKnownUniquelyReferenced(&_owner)) {
|
||||||
|
|
||||||
let bounds: Range<UnsafePointer<_RawByte>>
|
let bounds: Range<UnsafeRawPointer>
|
||||||
= UnsafePointer(_pointer(toElementAt:0))..<UnsafePointer(_pointer(toElementAt:count))
|
= UnsafeRawPointer(_pointer(toElementAt:0))
|
||||||
|
..< UnsafeRawPointer(_pointer(toElementAt:count))
|
||||||
|
|
||||||
if _fastPath(nativeBuffer!.hasCapacity(n, forSubRange: bounds)) {
|
if _fastPath(nativeBuffer!.hasCapacity(n, forSubRange: bounds)) {
|
||||||
return
|
return
|
||||||
@@ -700,13 +699,15 @@ extension _StringCore : RangeReplaceableCollection {
|
|||||||
let newSize = count + growth
|
let newSize = count + growth
|
||||||
let destination = _growBuffer(newSize, minElementWidth: width)
|
let destination = _growBuffer(newSize, minElementWidth: width)
|
||||||
if elementWidth == 1 {
|
if elementWidth == 1 {
|
||||||
let destination8 = UnsafeMutablePointer<UTF8.CodeUnit>(destination)
|
let destination8
|
||||||
|
= destination.assumingMemoryBound(to: UTF8.CodeUnit.self)
|
||||||
for i in 0..<growth {
|
for i in 0..<growth {
|
||||||
destination8[i] = UTF8.CodeUnit(iter.next()!)
|
destination8[i] = UTF8.CodeUnit(iter.next()!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let destination16 = UnsafeMutablePointer<UTF16.CodeUnit>(destination)
|
let destination16
|
||||||
|
= destination.assumingMemoryBound(to: UTF16.CodeUnit.self)
|
||||||
for i in 0..<growth {
|
for i in 0..<growth {
|
||||||
destination16[i] = iter.next()!
|
destination16[i] = iter.next()!
|
||||||
}
|
}
|
||||||
@@ -723,7 +724,6 @@ extension _StringCore : RangeReplaceableCollection {
|
|||||||
// storage have a non-NULL base address.
|
// storage have a non-NULL base address.
|
||||||
var _emptyStringStorage: UInt32 = 0
|
var _emptyStringStorage: UInt32 = 0
|
||||||
|
|
||||||
var _emptyStringBase: OpaquePointer {
|
var _emptyStringBase: UnsafeMutableRawPointer {
|
||||||
return OpaquePointer(
|
return UnsafeMutableRawPointer(Builtin.addressof(&_emptyStringStorage))
|
||||||
UnsafeMutablePointer<UInt16>(Builtin.addressof(&_emptyStringStorage)))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ extension _StringCore {
|
|||||||
var result: _UTF8Chunk = ~0 // Start with all bits set
|
var result: _UTF8Chunk = ~0 // Start with all bits set
|
||||||
|
|
||||||
_memcpy(
|
_memcpy(
|
||||||
dest: UnsafeMutablePointer(Builtin.addressof(&result)),
|
dest: UnsafeMutableRawPointer(Builtin.addressof(&result)),
|
||||||
src: UnsafeMutablePointer(startASCII + i),
|
src: startASCII + i,
|
||||||
size: numericCast(utf16Count))
|
size: numericCast(utf16Count))
|
||||||
|
|
||||||
// Convert the _UTF8Chunk into host endianness.
|
// Convert the _UTF8Chunk into host endianness.
|
||||||
|
|||||||
@@ -204,13 +204,15 @@ extension String {
|
|||||||
self._baseSet = true
|
self._baseSet = true
|
||||||
if _base.isASCII {
|
if _base.isASCII {
|
||||||
self._ascii = true
|
self._ascii = true
|
||||||
self._asciiBase = UnsafeBufferPointer<UInt8>(
|
self._asciiBase = UnsafeBufferPointer(
|
||||||
start: UnsafePointer(_base._baseAddress),
|
start: _base._baseAddress?.assumingMemoryBound(
|
||||||
|
to: UTF8.CodeUnit.self),
|
||||||
count: _base.count).makeIterator()
|
count: _base.count).makeIterator()
|
||||||
} else {
|
} else {
|
||||||
self._ascii = false
|
self._ascii = false
|
||||||
self._base = UnsafeBufferPointer<UInt16>(
|
self._base = UnsafeBufferPointer<UInt16>(
|
||||||
start: UnsafePointer(_base._baseAddress),
|
start: _base._baseAddress?.assumingMemoryBound(
|
||||||
|
to: UTF16.CodeUnit.self),
|
||||||
count: _base.count).makeIterator()
|
count: _base.count).makeIterator()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -629,16 +629,6 @@ extension UInt {
|
|||||||
}
|
}
|
||||||
% end # for mutable
|
% 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'}:
|
// ${'Local Variables'}:
|
||||||
// eval: (read-only-mode 1)
|
// eval: (read-only-mode 1)
|
||||||
// End:
|
// End:
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ func repr(_ x: _StringCore) -> String {
|
|||||||
if x.hasContiguousStorage {
|
if x.hasContiguousStorage {
|
||||||
if let b = x.nativeBuffer {
|
if let b = x.nativeBuffer {
|
||||||
var offset = x.elementWidth == 2
|
var offset = x.elementWidth == 2
|
||||||
? UnsafeMutablePointer(b.start) - x.startUTF16
|
? b.start - UnsafeMutableRawPointer(x.startUTF16)
|
||||||
: UnsafeMutablePointer(b.start) - x.startASCII
|
: b.start - UnsafeMutableRawPointer(x.startASCII)
|
||||||
return "Contiguous(owner: "
|
return "Contiguous(owner: "
|
||||||
+ "\(hexAddr(x._owner))[\(offset)...\(x.count + offset)]"
|
+ "\(hexAddr(x._owner))[\(offset)...\(x.count + offset)]"
|
||||||
+ ", capacity = \(b.capacity))"
|
+ ", capacity = \(b.capacity))"
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ func repr(_ x: _StringCore) -> String {
|
|||||||
if x.hasContiguousStorage {
|
if x.hasContiguousStorage {
|
||||||
if let b = x.nativeBuffer {
|
if let b = x.nativeBuffer {
|
||||||
var offset = x.elementWidth == 2
|
var offset = x.elementWidth == 2
|
||||||
? UnsafeMutablePointer(b.start) - x.startUTF16
|
? b.start - UnsafeMutableRawPointer(x.startUTF16)
|
||||||
: UnsafeMutablePointer(b.start) - x.startASCII
|
: b.start - UnsafeMutableRawPointer(x.startASCII)
|
||||||
return "Contiguous(owner: "
|
return "Contiguous(owner: "
|
||||||
+ "\(hexAddr(x._owner))[\(offset)...\(x.count + offset)]"
|
+ "\(hexAddr(x._owner))[\(offset)...\(x.count + offset)]"
|
||||||
+ ", capacity = \(b.capacity))"
|
+ ", capacity = \(b.capacity))"
|
||||||
|
|||||||
Reference in New Issue
Block a user