[String] Custom iterator for UTF16View (#20929)

Defining a custom iterator for the UTF16View avoid some redundant
computation over the indexing model. This speeds up iteration by
around 40% on non-ASCII strings.
This commit is contained in:
Michael Ilseman
2018-12-01 09:35:27 -08:00
committed by GitHub
parent 1c91dd4933
commit b01ee7267a
4 changed files with 59 additions and 3 deletions

View File

@@ -234,8 +234,8 @@ extension String {
@inlinable
internal init(_ guts: _StringGuts) {
self._guts = guts
self._end = guts.count
self._guts = guts
}
@inlinable

View File

@@ -260,6 +260,59 @@ extension String.UTF16View: BidirectionalCollection {
}
}
}
extension String.UTF16View {
@_fixed_layout
public struct Iterator: IteratorProtocol {
@usableFromInline
internal var _guts: _StringGuts
@usableFromInline
internal var _position: Int = 0
@usableFromInline
internal var _end: Int
// If non-nil, return this value for `next()` (and set it to nil).
//
// This is set when visiting a non-BMP scalar: the leading surrogate is
// returned, this field is set with the value of the trailing surrogate, and
// `_position` is advanced to the start of the next scalar.
@usableFromInline
internal var _nextIsTrailingSurrogate: UInt16? = nil
@inlinable
internal init(_ guts: _StringGuts) {
self._end = guts.count
self._guts = guts
}
@inlinable
public mutating func next() -> UInt16? {
if _slowPath(_nextIsTrailingSurrogate != nil) {
let trailing = self._nextIsTrailingSurrogate._unsafelyUnwrappedUnchecked
self._nextIsTrailingSurrogate = nil
return trailing
}
guard _fastPath(_position < _end) else { return nil }
let (scalar, len) = _guts.errorCorrectedScalar(startingAt: _position)
_position &+= len
if _slowPath(scalar.value > UInt16.max) {
self._nextIsTrailingSurrogate = scalar.utf16[1]
return scalar.utf16[0]
}
return UInt16(truncatingIfNeeded: scalar.value)
}
}
@inlinable
public __consuming func makeIterator() -> Iterator {
return Iterator(_guts)
}
}
extension String.UTF16View: CustomStringConvertible {
@inlinable
public var description: String {

View File

@@ -180,8 +180,8 @@ extension String.UnicodeScalarView {
@inlinable
internal init(_ guts: _StringGuts) {
self._guts = guts
self._end = guts.count
self._guts = guts
}
@inlinable

View File

@@ -499,6 +499,9 @@ Var _StringGutsSlice.isNFCFastUTF8 has been removed
Var _StringGutsSlice.range has been removed
Var _StringGutsSlice.start has been removed
Struct String.UTF16View has type witness type for Collection.Iterator changing from IndexingIterator<String.UTF16View> to String.UTF16View.Iterator
Struct String.UTF16View has type witness type for Sequence.Iterator changing from IndexingIterator<String.UTF16View> to String.UTF16View.Iterator
Func ManagedBufferPointer._sanityCheckValidBufferClass(_:creating:) has been removed
Func _sanityCheck(_:_:file:line:) has been removed
Func _sanityCheckFailure(_:file:line:) has been removed