@@ -227,14 +227,13 @@ internal
227
227
struct _NormalizedUTF16CodeUnitIterator : IteratorProtocol {
228
228
internal typealias CodeUnit = UInt16
229
229
var segmentBuffer = _FixedArray16 < CodeUnit > ( allZeros: ( ) )
230
- var overflowBuffer : [ CodeUnit ] ? = nil
231
- var normalizationBuffer : [ CodeUnit ] ? = nil
230
+ var normalizationBuffer = _FixedArray16 < CodeUnit > ( allZeros: ( ) )
231
+ var segmentHeapBuffer : [ CodeUnit ] ? = nil
232
+ var normalizationHeapBuffer : [ CodeUnit ] ? = nil
232
233
var source : _SegmentSource
233
234
234
235
var segmentBufferIndex = 0
235
236
var segmentBufferCount = 0
236
- var overflowBufferIndex = 0
237
- var overflowBufferCount = 0
238
237
239
238
init ( _ guts: _StringGuts , _ range: Range < String . Index > ) {
240
239
source = _ForeignStringGutsSource ( guts, range)
@@ -350,83 +349,86 @@ struct _NormalizedUTF16CodeUnitIterator: IteratorProtocol {
350
349
351
350
mutating func next( ) -> UInt16 ? {
352
351
if segmentBufferCount == segmentBufferIndex {
352
+ if source. isEmpty {
353
+ return nil
354
+ }
353
355
segmentBuffer = _FixedArray16 < CodeUnit > ( allZeros: ( ) )
354
356
segmentBufferCount = 0
355
357
segmentBufferIndex = 0
356
358
}
357
-
358
- if overflowBufferCount == overflowBufferIndex {
359
- overflowBufferCount = 0
360
- overflowBufferIndex = 0
359
+
360
+ if segmentBufferCount == 0 {
361
+ segmentBufferCount = normalizeFromSource ( )
361
362
}
362
363
363
- if source. isEmpty
364
- && segmentBufferCount == 0
365
- && overflowBufferCount == 0 {
366
- // Our source of code units to normalize is empty and our buffers from
367
- // previous normalizations are also empty.
368
- return nil
364
+ guard segmentBufferIndex < segmentBufferCount else { return nil }
365
+
366
+ defer { segmentBufferIndex += 1 }
367
+ if _slowPath ( segmentHeapBuffer != nil ) {
368
+ return segmentHeapBuffer![ segmentBufferIndex]
369
369
}
370
- if segmentBufferCount == 0 && overflowBufferCount == 0 {
371
- //time to fill a buffer if possible. Otherwise we are done, return nil
372
- // Normalize segment, and then compare first code unit
373
- var intermediateBuffer = _FixedArray16 < CodeUnit > ( allZeros: ( ) )
374
- if overflowBuffer == nil ,
375
- let filled = source. tryFill ( into: & intermediateBuffer)
376
- {
377
- guard let count = _tryNormalize (
378
- _castOutputBuffer ( & intermediateBuffer,
379
- endingAt: filled) ,
380
- into: & segmentBuffer
381
- )
382
- else {
383
- fatalError ( " Output buffer was not big enough, this should not happen " )
384
- }
385
- segmentBufferCount = count
386
- } else {
387
- if overflowBuffer == nil {
388
- let size = source. remaining * _Normalization. _maxNFCExpansionFactor
389
- overflowBuffer = Array ( repeating: 0 , count: size)
390
- normalizationBuffer = Array ( repeating: 0 , count: size)
391
- }
392
-
393
- guard let count = normalizationBuffer!. withUnsafeMutableBufferPointer ( {
394
- ( normalizationBufferPtr) -> Int ? in
395
- guard let filled = source. tryFill ( into: normalizationBufferPtr)
396
- else {
397
- fatalError ( " Invariant broken, buffer should have space " )
398
- }
399
- return overflowBuffer!. withUnsafeMutableBufferPointer {
400
- ( overflowBufferPtr) -> Int ? in
401
- return _tryNormalize (
402
- UnsafeBufferPointer ( rebasing: normalizationBufferPtr [ ..< filled] ) ,
403
- into: overflowBufferPtr
404
- )
405
- }
406
- } ) else {
407
- fatalError ( " Invariant broken, overflow buffer should have space " )
408
- }
409
-
410
- overflowBufferCount = count
370
+ return segmentBuffer [ segmentBufferIndex]
371
+ }
372
+
373
+ mutating func normalizeFromSource( ) -> Int {
374
+ if segmentHeapBuffer == nil ,
375
+ let filled = source. tryFill ( into: & normalizationBuffer)
376
+ {
377
+ if let count = _tryNormalize (
378
+ _castOutputBuffer ( & normalizationBuffer,
379
+ endingAt: filled) ,
380
+ into: & segmentBuffer
381
+ ) {
382
+ return count
411
383
}
384
+ return normalizeWithHeapBuffers ( filled)
412
385
}
413
-
414
- //exactly one of the buffers should have code units for us to return
415
- _internalInvariant ( ( segmentBufferCount == 0 )
416
- != ( ( overflowBuffer? . count ?? 0 ) == 0 ) )
417
-
418
- if segmentBufferIndex < segmentBufferCount {
419
- let index = segmentBufferIndex
420
- segmentBufferIndex += 1
421
- return segmentBuffer [ index]
422
- } else if overflowBufferIndex < overflowBufferCount {
423
- _internalInvariant ( overflowBufferIndex < overflowBuffer!. count)
424
- let index = overflowBufferIndex
425
- overflowBufferIndex += 1
426
- return overflowBuffer![ index]
427
- } else {
428
- return nil
386
+ return normalizeWithHeapBuffers ( )
387
+ }
388
+
389
+ //This handles normalization from an intermediate buffer to the heap segment
390
+ //buffer. This can get called in 3 situations:
391
+ //* We've already transitioned to heap buffers
392
+ //* We attempted to fill the pre-normal stack buffer but there was not enough
393
+ //. room, so we need to promote both and then attempt the fill again.
394
+ //* The fill for the stack buffer succeeded, but the normalization didn't. In
395
+ // this case, we want to first copy the contents of the stack buffer that
396
+ // we filled into the new heap buffer. The stackBufferCount
397
+ // parameter signals that we need to do this copy, thus skipping the fill
398
+ // that we would normally do before normalization.
399
+ mutating func normalizeWithHeapBuffers(
400
+ _ stackBufferCount: Int ? = nil
401
+ ) -> Int {
402
+ if segmentHeapBuffer == nil {
403
+ _internalInvariant ( normalizationHeapBuffer == nil )
404
+ let preFilledBufferCount = stackBufferCount ?? 0
405
+ let size = ( source. remaining + preFilledBufferCount)
406
+ * _Normalization. _maxNFCExpansionFactor
407
+ segmentHeapBuffer = Array ( repeating: 0 , count: size)
408
+ normalizationHeapBuffer = Array ( repeating: 0 , count: size)
409
+ for i in 0 ..< preFilledBufferCount {
410
+ normalizationHeapBuffer![ i] = normalizationBuffer [ i]
411
+ }
412
+ }
413
+
414
+ guard let count = normalizationHeapBuffer!. withUnsafeMutableBufferPointer ( {
415
+ ( normalizationHeapBufferPtr) -> Int ? in
416
+ guard let filled = stackBufferCount ??
417
+ source. tryFill ( into: normalizationHeapBufferPtr)
418
+ else {
419
+ fatalError ( " Invariant broken, buffer should have space " )
420
+ }
421
+ return segmentHeapBuffer!. withUnsafeMutableBufferPointer {
422
+ ( segmentHeapBufferPtr) -> Int ? in
423
+ return _tryNormalize (
424
+ UnsafeBufferPointer ( rebasing: normalizationHeapBufferPtr [ ..< filled] ) ,
425
+ into: segmentHeapBufferPtr
426
+ )
427
+ }
428
+ } ) else {
429
+ fatalError ( " Invariant broken, overflow buffer should have space " )
429
430
}
431
+ return count
430
432
}
431
433
}
432
434
@@ -635,22 +637,19 @@ extension _NormalizedUTF8CodeUnitIterator_2 {
635
637
let result = _lexicographicalCompare ( cu, otherCU)
636
638
if result == . equal {
637
639
continue
638
- } else {
639
- return result
640
640
}
641
- } else {
642
- //other returned nil, we are greater
643
- return . greater
641
+ return result
644
642
}
643
+ //other returned nil, we are greater
644
+ return . greater
645
645
}
646
646
647
647
//we ran out of code units, either we are equal, or only we ran out and
648
648
//other is greater
649
649
if let _ = mutableOther. next ( ) {
650
650
return . less
651
- } else {
652
- return . equal
653
651
}
652
+ return . equal
654
653
}
655
654
}
656
655
0 commit comments