Skip to content

Commit 3127444

Browse files
committed
[stdlib] String: Tweak Iterator
Rwrite the current iterator’s `next` implementation to use the new grapheme breaking primitives instead of forwarding to `_opaqueCharacterStride(startingAt:)`. Unfortunately `String.Iterator` is a frozen type and its members used to be fully inlinable, so we can’t (easily) remember the grapheme breaking state across `next` invocations. Frustrating! 😖
1 parent 7a6a296 commit 3127444

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

stdlib/public/core/StringCharacterView.swift

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -405,14 +405,23 @@ extension String {
405405
}
406406

407407
public mutating func next() -> Character? {
408-
// Prior to Swift 5.7, this function used to be inlinable.
408+
// Prior to Swift 5.7, this function used to be inlinable,
409+
// calling `_opaqueCharacterStride(startingAt: _position)`.
410+
409411
guard _fastPath(_position < _end) else { return nil }
410412

411-
let len = _guts._opaqueCharacterStride(startingAt: _position)
412-
let nextPosition = _position &+ len
413+
// Ideally we would preserve the state across iterations, but sadly this
414+
// struct is frozen and we can't stash the state anywhere. This entire
415+
// iterator used to be inlinable, so we can't change the meaning of stored
416+
// properties -- even though it would be tempting to repurpose `_end`.
417+
//
418+
// FIXME: Perhaps we could hide the state bits within the reserved flags
419+
// of _guts -- we have plenty of room there for the gbp...
420+
var p = _guts.forwardGraphemeBreakingState(at: _position, with: nil)
421+
_guts.formNextGraphemeBreak(after: &p)
413422
let result = _guts.errorCorrectedCharacter(
414-
startingAt: _position, endingAt: nextPosition)
415-
_position = nextPosition
423+
startingAt: _position, endingAt: p.offset)
424+
_position = p.offset
416425
return result
417426
}
418427
}

0 commit comments

Comments
 (0)