mirror of
https://github.com/apple/swift.git
synced 2026-06-20 15:42:51 +02:00
453277eb74
Functions like withUnsafeBufferPointer are, by themselves, safe to call. It's only the operations on the unsafe pointers passed into the closure that are the safety issue. This was the intent spelled out in SE-0458 but was not fully realized in the library. Fixes rdar://174519372.
99 lines
2.9 KiB
Swift
99 lines
2.9 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2026 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TODO(String performance): Unfortunately, this slice struct seems to add
|
|
// overhead. We may want to wean ourselves off of this and have all users just
|
|
// also store a range.
|
|
|
|
// A sliced _StringGuts, convenient for unifying String/Substring comparison,
|
|
// hashing, and RRC.
|
|
internal struct _StringGutsSlice {
|
|
internal var _guts: _StringGuts
|
|
|
|
internal var _offsetRange: Range<Int>
|
|
|
|
@inline(__always)
|
|
internal init(_ guts: _StringGuts) {
|
|
self._guts = guts
|
|
self._offsetRange = unsafe Range(_uncheckedBounds: (0, guts.count))
|
|
}
|
|
|
|
@inline(__always)
|
|
internal init(_ guts: _StringGuts, _ offsetRange: Range<Int>) {
|
|
_internalInvariant(
|
|
offsetRange.lowerBound >= 0 && offsetRange.upperBound <= guts.count)
|
|
self._guts = guts
|
|
self._offsetRange = offsetRange
|
|
}
|
|
|
|
internal var start: Int {
|
|
@inline(__always) get { return _offsetRange.lowerBound }
|
|
}
|
|
|
|
internal var end: Int {
|
|
@inline(__always) get { return _offsetRange.upperBound }
|
|
}
|
|
|
|
internal var count: Int {
|
|
@inline(__always) get { return _offsetRange.count }
|
|
}
|
|
|
|
internal var isNFCFastUTF8: Bool {
|
|
@inline(__always) get { return _guts.isNFCFastUTF8 }
|
|
}
|
|
|
|
internal var isASCII: Bool {
|
|
@inline(__always) get { return _guts.isASCII }
|
|
}
|
|
|
|
internal var isFastUTF8: Bool {
|
|
@inline(__always) get { return _guts.isFastUTF8 }
|
|
}
|
|
|
|
internal var utf8Count: Int {
|
|
@inline(__always) get {
|
|
if _fastPath(self.isFastUTF8) {
|
|
return _offsetRange.count
|
|
}
|
|
return Substring(self).utf8.count
|
|
}
|
|
}
|
|
|
|
internal var range: Range<String.Index> {
|
|
@inline(__always) get {
|
|
let lower = String.Index(_encodedOffset: _offsetRange.lowerBound)
|
|
._scalarAligned
|
|
let higher = String.Index(_encodedOffset: _offsetRange.upperBound)
|
|
._scalarAligned
|
|
return unsafe Range(_uncheckedBounds: (lower, higher))
|
|
}
|
|
}
|
|
|
|
@inline(__always)
|
|
internal func withFastUTF8<R, E: Error>(
|
|
_ f: (UnsafeBufferPointer<UInt8>) throws(E) -> R
|
|
) throws(E) -> R {
|
|
return try _guts.withFastUTF8(range: _offsetRange, f)
|
|
}
|
|
|
|
@_effects(releasenone)
|
|
internal func foreignErrorCorrectedScalar(
|
|
startingAt idx: String.Index
|
|
) -> (Unicode.Scalar, scalarLength: Int) {
|
|
let (scalar, len) = _guts.foreignErrorCorrectedScalar(startingAt: idx)
|
|
if _slowPath(idx.encoded(offsetBy: len) > range.upperBound) {
|
|
return (Unicode.Scalar._replacementCharacter, 1)
|
|
}
|
|
return (scalar, len)
|
|
}
|
|
}
|