mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-10-31 17:15:28 +08:00 
			
		
		
		
	Adds a segment builder for merging multiple segments
When merging a large amount of segments together we were doing a tremendous amount of allocation especially related to strings due to concatination. This adds an internal SegmentBuilder that uses a stringbuilder for building up the text rather than creating a new instance and doing a concat operation for each segment.
This commit is contained in:
		 Phil Scott
					Phil Scott
				
			
				
					committed by
					
						 Patrik Svensson
						Patrik Svensson
					
				
			
			
				
	
			
			
			 Patrik Svensson
						Patrik Svensson
					
				
			
						parent
						
							64f444114a
						
					
				
				
					commit
					ad23855b0a
				
			| @@ -449,36 +449,36 @@ namespace Spectre.Console.Rendering | ||||
|  | ||||
|             var result = new List<Segment>(); | ||||
|  | ||||
|             var previous = (Segment?)null; | ||||
|             var segmentBuilder = (SegmentBuilder?)null; | ||||
|             foreach (var segment in segments) | ||||
|             { | ||||
|                 if (previous == null) | ||||
|                 if (segmentBuilder == null) | ||||
|                 { | ||||
|                     previous = segment; | ||||
|                     segmentBuilder = new SegmentBuilder(segment); | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 // Both control codes? | ||||
|                 if (segment.IsControlCode && previous.IsControlCode) | ||||
|                 if (segment.IsControlCode && segmentBuilder.IsControlCode()) | ||||
|                 { | ||||
|                     previous = Control(previous.Text + segment.Text); | ||||
|                     segmentBuilder.Append(segment.Text); | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 // Same style? | ||||
|                 if (previous.Style.Equals(segment.Style) && !previous.IsLineBreak && !previous.IsControlCode) | ||||
|                 if (segmentBuilder.StyleEquals(segment.Style) && !segmentBuilder.IsLineBreak() && !segmentBuilder.IsControlCode()) | ||||
|                 { | ||||
|                     previous = new Segment(previous.Text + segment.Text, previous.Style); | ||||
|                     segmentBuilder.Append(segment.Text); | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 result.Add(previous); | ||||
|                 previous = segment; | ||||
|                 result.Add(segmentBuilder.Build()); | ||||
|                 segmentBuilder.Reset(segment); | ||||
|             } | ||||
|  | ||||
|             if (previous != null) | ||||
|             if (segmentBuilder != null) | ||||
|             { | ||||
|                 result.Add(previous); | ||||
|                 result.Add(segmentBuilder.Build()); | ||||
|             } | ||||
|  | ||||
|             return result; | ||||
| @@ -579,5 +579,39 @@ namespace Spectre.Console.Rendering | ||||
|  | ||||
|             return list; | ||||
|         } | ||||
|  | ||||
|         private class SegmentBuilder | ||||
|         { | ||||
|             private readonly StringBuilder _textBuilder = new(); | ||||
|             private Segment _originalSegment; | ||||
|  | ||||
|             public SegmentBuilder(Segment originalSegment) | ||||
|             { | ||||
|                 _originalSegment = originalSegment; | ||||
|                 Reset(originalSegment); | ||||
|             } | ||||
|  | ||||
|             public bool IsControlCode() => _originalSegment.IsControlCode; | ||||
|             public bool IsLineBreak() => _originalSegment.IsLineBreak; | ||||
|             public bool StyleEquals(Style segmentStyle) => segmentStyle.Equals(_originalSegment.Style); | ||||
|  | ||||
|             public void Append(string text) | ||||
|             { | ||||
|                 _textBuilder.Append(text); | ||||
|             } | ||||
|  | ||||
|             public Segment Build() | ||||
|             { | ||||
|                 return new Segment(_textBuilder.ToString(), _originalSegment.Style, _originalSegment.IsLineBreak, | ||||
|                     _originalSegment.IsControlCode); | ||||
|             } | ||||
|  | ||||
|             public void Reset(Segment segment) | ||||
|             { | ||||
|                 _textBuilder.Clear(); | ||||
|                 _textBuilder.Append(segment.Text); | ||||
|                 _originalSegment = segment; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user