Uses StringBuilder and char span indexof search to reduce intermediate allocations.
The new implementation behaves slightly different compared to old implementation. In synthetic LFCR scenario it is correctly removed while the old implementation left the CR, which seems like an off-by-one error.
* Subview clean up
* New Add/Remove event pattern
* Using Logging
* cleanup
* Subview -> SubView
* Test code cleanup. Killed many warnings.
* Fix tznind feedback
* Refactored AllViewTest helpers
* Moved keyboard tests to parallel
* Moved mouse tests to parallel
* Moved view tests to parallel
* Test code cleanup. Killed many warnings.
* dupe test
* Some mouse tests can't run in parallel because MouseGrabView
* Made SpinnerView more testable
* Moved more tests
* SubViews to IReadOnlyCollection<View>
* SubViews to IReadOnlyCollection<View> 2
* scrollbar tests
* shortcut tests
* Use InternalSubViews vs. _subviews
* Nuked View.IsAdded.
Added View.SuperViewChanged.
* API doc updats
* Unit Test tweak
* Unit Test tweak
* Replace Region.Contains LINQ lambdas with foreach loop
Removes the lambda func allocations caused by captured outer variables.
* Replace LineCanvas.Has LINQ lambda with foreach loop
* Fix LineCanvas.GetMap intersects array nullability
It should be enough to add null-forgiving operator somewhere in the LINQ query to make the final result non-null. No need to shove the nullability further down the line to complicate things. :)
* Replace LineCanvas.All LINQ lambda with foreach loop
* Replace Region.Intersect LINQ lambdas and list allocation with foreach loop and rented array
* Use stackalloc buffer in Region.Intersect when max 8 rectangles
* Fix LineCanvas.GetCellMap intersects array nullability
* Remove leftover LineCanvas.GetRuneForIntersects null-conditional operators
* Remove leftover IntersectionRuneResolver.GetRuneForIntersects null-conditional operators
* PosAlign.CalculateMinDimension: calculate sum during loop
No need to first put the dimensions in a list and then sum the list when you can just add to sum while looping through dimensions.
* PosAlign.CalculateMinDimension: Remove intermediate list and related filter func allocation
* TextFormatter.GetRuneWidth: Remove intermediate list and related sum func allocation
* ReadOnlySpan refactor preparation for GetCellMap rewrite
* LineCanvas.GetCellMap: Reuse intersection list outside nested loops
GetCellMap would not benefit much from array pool because IntersectionDefinition is not struct. This change eliminates majority of the rest of Func<,> allocations. As a bonus IntersectionDefinition[] allocations dropped nicely.
* Refactor local method UseRounded
* Wrap too long list of method parameters
* Region: Consistent location for #nullable enable
---------
Co-authored-by: Tig <tig@users.noreply.github.com>
* Add benchmarks for potentially optimizable RuneExtensions
* Add new RuneExtensions.DecodeSurrogatePair benchmark implementation
Avoids intermediate heap array allocations which is especially nice when the rune is not surrogate pair because then array heap allocations are completely avoided.
* Enable nullable reference types in RuneExtensions
* Make RuneExtensions.MaxUnicodeCodePoint readonly
Makes sure no one can accidentally change the value. Ideally would be const value.
* Optimize RuneExtensions.DecodeSurrogatePair
* Remove duplicate Rune.GetUnicodeCategory call
* Add new RuneExtensions.IsSurrogatePair benchmark implementation
Avoids intermediate heap allocations by using stack allocated buffer.
* Optimize RuneExtensions.IsSurrogatePair
* Add RuneExtensions.GetEncodingLength tests
* Optimize RuneExtensions.GetEncodingLength
* Optimize RuneExtensions.Encode
* Print encoding name in benchmark results
* Rename variable to better match return description
* Add RuneExtensions.EncodeSurrogatePair benchmark
---------
Co-authored-by: Tig <tig@users.noreply.github.com>