From 2e4e73a436fed86366f0267ef9ecc0a0dbd1af9a Mon Sep 17 00:00:00 2001
From: Tonttu <15074459+TheTonttu@users.noreply.github.com>
Date: Sun, 16 Mar 2025 00:19:06 +0200
Subject: [PATCH] Rewrite TextFormatter.RemoveHotKeySpecifier
Uses stackalloc char buffer with fallback to rented array.
---
.../TextFormatter/RemoveHotKeySpecifier.cs | 97 +++++++++++++++++++
Terminal.Gui/Text/TextFormatter.cs | 46 ++++++---
2 files changed, 130 insertions(+), 13 deletions(-)
create mode 100644 Benchmarks/Text/TextFormatter/RemoveHotKeySpecifier.cs
diff --git a/Benchmarks/Text/TextFormatter/RemoveHotKeySpecifier.cs b/Benchmarks/Text/TextFormatter/RemoveHotKeySpecifier.cs
new file mode 100644
index 000000000..e72dc0e1e
--- /dev/null
+++ b/Benchmarks/Text/TextFormatter/RemoveHotKeySpecifier.cs
@@ -0,0 +1,97 @@
+using System.Text;
+using BenchmarkDotNet.Attributes;
+using Tui = Terminal.Gui;
+
+namespace Terminal.Gui.Benchmarks.Text.TextFormatter;
+
+///
+/// Benchmarks for performance fine-tuning.
+///
+[MemoryDiagnoser]
+[BenchmarkCategory (nameof(Tui.TextFormatter))]
+public class RemoveHotKeySpecifier
+{
+ // Omit from summary table.
+ private static readonly Rune HotkeySpecifier = (Rune)'_';
+
+ ///
+ /// Benchmark for previous implementation.
+ ///
+ [Benchmark]
+ [ArgumentsSource (nameof (DataSource))]
+ public string Previous (string text, int hotPos)
+ {
+ return StringConcatLoop (text, hotPos, HotkeySpecifier);
+ }
+
+ ///
+ /// Benchmark for current implementation with stackalloc char buffer and fallback to rented array.
+ ///
+ [Benchmark (Baseline = true)]
+ [ArgumentsSource (nameof (DataSource))]
+ public string Current (string text, int hotPos)
+ {
+ return Tui.TextFormatter.RemoveHotKeySpecifier (text, hotPos, HotkeySpecifier);
+ }
+
+ ///
+ /// Previous implementation with string concatenation in a loop.
+ ///
+ public static string StringConcatLoop (string text, int hotPos, Rune hotKeySpecifier)
+ {
+ if (string.IsNullOrEmpty (text))
+ {
+ return text;
+ }
+
+ // Scan
+ var start = string.Empty;
+ var i = 0;
+
+ foreach (Rune c in text.EnumerateRunes ())
+ {
+ if (c == hotKeySpecifier && i == hotPos)
+ {
+ i++;
+
+ continue;
+ }
+
+ start += c;
+ i++;
+ }
+
+ return start;
+ }
+
+ public IEnumerable