Skip to content

Commit 781b3eb

Browse files
lorenteymilseman
authored andcommitted
_StringGuts: Implement Sequence with a buffering iterator
Having this simplifies migrating the UTF-8 view away from _LegacyStringCore, but we should probably get rid of it at some point. Using a 16-element buffer here is probably overkill.
1 parent 60fff84 commit 781b3eb

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

stdlib/public/core/StringGuts.swift

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,3 +1127,73 @@ extension _StringGuts {
11271127
}
11281128
}
11291129
}
1130+
1131+
extension _StringGuts : Sequence {
1132+
public typealias Element = UTF16.CodeUnit
1133+
1134+
@_fixed_layout
1135+
public struct Iterator : IteratorProtocol {
1136+
public typealias Element = UTF16.CodeUnit
1137+
1138+
@_versioned
1139+
internal let _guts: _StringGuts
1140+
@_versioned
1141+
internal let _endOffset: Int
1142+
@_versioned
1143+
internal var _nextOffset: Int
1144+
@_versioned
1145+
internal var _buffer = _FixedArray16<Element>()
1146+
@_versioned
1147+
internal var _bufferIndex: Int = 0
1148+
1149+
@_inlineable
1150+
@_versioned
1151+
internal init(_ guts: _StringGuts, range: Range<Int>) {
1152+
self._guts = guts
1153+
self._endOffset = range.upperBound
1154+
self._nextOffset = range.lowerBound
1155+
if _fastPath(!range.isEmpty) {
1156+
_fillBuffer()
1157+
}
1158+
}
1159+
1160+
@_inlineable
1161+
public mutating func next() -> Element? {
1162+
if _fastPath(_bufferIndex < _buffer.count) {
1163+
let result = _buffer[_bufferIndex]
1164+
_bufferIndex += 1
1165+
return result
1166+
}
1167+
if _nextOffset == _endOffset {
1168+
return nil
1169+
}
1170+
_fillBuffer()
1171+
_bufferIndex = 1
1172+
return _buffer[0]
1173+
}
1174+
1175+
@_versioned
1176+
@inline(never)
1177+
internal mutating func _fillBuffer() {
1178+
_sanityCheck(_buffer.count == 0)
1179+
_buffer.count = Swift.min(_buffer.capacity, _endOffset - _nextOffset)
1180+
_sanityCheck(_buffer.count > 0)
1181+
_buffer.withUnsafeMutableBufferPointer { buffer in
1182+
let range: Range<Int> = _nextOffset ..< _nextOffset + buffer.count
1183+
_guts._copy(range: range, into: buffer)
1184+
}
1185+
_nextOffset += _buffer.count
1186+
}
1187+
}
1188+
1189+
@_inlineable
1190+
public func makeIterator() -> Iterator {
1191+
return Iterator(self, range: 0..<count)
1192+
}
1193+
1194+
@_inlineable
1195+
@_versioned
1196+
internal func makeIterator(in range: Range<Int>) -> Iterator {
1197+
return Iterator(self, range: range)
1198+
}
1199+
}

0 commit comments

Comments
 (0)