diff --git a/Dalamud/Game/Gui/ChatGui.cs b/Dalamud/Game/Gui/ChatGui.cs index d7303c4ce..30e2b676c 100644 --- a/Dalamud/Game/Gui/ChatGui.cs +++ b/Dalamud/Game/Gui/ChatGui.cs @@ -26,7 +26,6 @@ using Lumina.Text; using Lumina.Text.Payloads; using Lumina.Text.ReadOnly; -using LSeStringBuilder = Lumina.Text.SeStringBuilder; using SeString = Dalamud.Game.Text.SeStringHandling.SeString; using SeStringBuilder = Dalamud.Game.Text.SeStringHandling.SeStringBuilder; @@ -207,21 +206,21 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui if (this.chatQueue.Count == 0) return; - var sb = LSeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); Span namebuf = stackalloc byte[256]; using var sender = new Utf8String(); using var message = new Utf8String(); while (this.chatQueue.TryDequeue(out var chat)) { - sb.Clear(); + rssb.Builder.Clear(); foreach (var c in UtfEnumerator.From(chat.MessageBytes, UtfEnumeratorFlags.Utf8SeString)) { if (c.IsSeStringPayload) - sb.Append((ReadOnlySeStringSpan)chat.MessageBytes.AsSpan(c.ByteOffset, c.ByteLength)); + rssb.Builder.Append((ReadOnlySeStringSpan)chat.MessageBytes.AsSpan(c.ByteOffset, c.ByteLength)); else if (c.Value.IntValue == 0x202F) - sb.BeginMacro(MacroCode.NonBreakingSpace).EndMacro(); + rssb.Builder.BeginMacro(MacroCode.NonBreakingSpace).EndMacro(); else - sb.Append(c); + rssb.Builder.Append(c); } if (chat.NameBytes.Length + 1 < namebuf.Length) @@ -235,7 +234,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui sender.SetString(chat.NameBytes.NullTerminate()); } - message.SetString(sb.GetViewAsSpan()); + message.SetString(rssb.Builder.GetViewAsSpan()); var targetChannel = chat.Type ?? this.configuration.GeneralChatType; @@ -247,8 +246,6 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui chat.Timestamp, (byte)(chat.Silent ? 1 : 0)); } - - LSeStringBuilder.SharedPool.Return(sb); } /// @@ -326,29 +323,28 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui private void PrintTagged(ReadOnlySpan message, XivChatType channel, string? tag, ushort? color) { - var sb = LSeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); if (!tag.IsNullOrEmpty()) { if (color is not null) { - sb.PushColorType(color.Value); - sb.Append($"[{tag}] "); - sb.PopColorType(); + rssb.Builder + .PushColorType(color.Value) + .Append($"[{tag}] ") + .PopColorType(); } else { - sb.Append($"[{tag}] "); + rssb.Builder.Append($"[{tag}] "); } } this.Print(new XivChatEntry { - MessageBytes = sb.Append((ReadOnlySeStringSpan)message).ToArray(), + MessageBytes = rssb.Builder.Append((ReadOnlySeStringSpan)message).ToArray(), Type = channel, }); - - LSeStringBuilder.SharedPool.Return(sb); } private void InventoryItemCopyDetour(InventoryItem* thisPtr, InventoryItem* otherPtr) @@ -457,7 +453,8 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui Log.Verbose($"InteractableLinkClicked: {Payload.EmbeddedInfoType.DalamudLink}"); - var sb = LSeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); + try { var seStringSpan = new ReadOnlySeStringSpan(linkData->Payload); @@ -465,7 +462,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui // read until link terminator foreach (var payload in seStringSpan) { - sb.Append(payload); + rssb.Builder.Append(payload); if (payload.Type == ReadOnlySePayloadType.Macro && payload.MacroCode == MacroCode.Link && @@ -477,7 +474,7 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui } } - var seStr = SeString.Parse(sb.ToArray()); + var seStr = SeString.Parse(rssb.Builder.ToArray()); if (seStr.Payloads.Count == 0 || seStr.Payloads[0] is not DalamudLinkPayload link) return; @@ -495,10 +492,6 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui { Log.Error(ex, "Exception in HandleLinkClickDetour"); } - finally - { - LSeStringBuilder.SharedPool.Return(sb); - } } } diff --git a/Dalamud/Game/Internal/DalamudCompletion.cs b/Dalamud/Game/Internal/DalamudCompletion.cs index e3564c823..50816a603 100644 --- a/Dalamud/Game/Internal/DalamudCompletion.cs +++ b/Dalamud/Game/Internal/DalamudCompletion.cs @@ -11,8 +11,6 @@ using FFXIVClientStructs.FFXIV.Client.UI; using FFXIVClientStructs.FFXIV.Component.Completion; using FFXIVClientStructs.FFXIV.Component.GUI; -using Lumina.Text; - namespace Dalamud.Game.Internal; /// @@ -253,16 +251,14 @@ internal sealed unsafe class DalamudCompletion : IInternalDisposableService { public EntryStrings(string command) { - var rssb = SeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); - this.Display = Utf8String.FromSequence(rssb + this.Display = Utf8String.FromSequence(rssb.Builder .PushColorType(539) .Append(command) .PopColorType() .GetViewAsSpan()); - SeStringBuilder.SharedPool.Return(rssb); - this.Match = Utf8String.FromString(command); } diff --git a/Dalamud/Game/Text/Evaluator/SeStringEvaluator.cs b/Dalamud/Game/Text/Evaluator/SeStringEvaluator.cs index 58bcdbd0b..f05c15263 100644 --- a/Dalamud/Game/Text/Evaluator/SeStringEvaluator.cs +++ b/Dalamud/Game/Text/Evaluator/SeStringEvaluator.cs @@ -102,16 +102,15 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator // TODO: remove culture info toggling after supporting CultureInfo for SeStringBuilder.Append, // and then remove try...finally block (discard builder from the pool on exception) var previousCulture = CultureInfo.CurrentCulture; - var builder = SeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); try { CultureInfo.CurrentCulture = Localization.GetCultureInfoFromLangCode(lang.ToCode()); - return this.EvaluateAndAppendTo(builder, str, localParameters, lang).ToReadOnlySeString(); + return this.EvaluateAndAppendTo(rssb.Builder, str, localParameters, lang).ToReadOnlySeString(); } finally { CultureInfo.CurrentCulture = previousCulture; - SeStringBuilder.SharedPool.Return(builder); } } @@ -930,7 +929,8 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator itemId += 1000000; } - var sb = SeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); + var sb = rssb.Builder; sb.Append(this.EvaluateFromAddon(6, [rarity], context.Language)); @@ -956,7 +956,6 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator sb.PopLink(); text = sb.ToReadOnlySeString(); - SeStringBuilder.SharedPool.Return(sb); } private void CreateSheetLink(in SeStringContext context, string resolvedSheetName, ReadOnlySeString text, uint eRowIdValue, uint eColParamValue) @@ -1028,40 +1027,33 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator if (!payload.TryGetExpression(out var eStr)) return false; - var builder = SeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); - try + var headContext = new SeStringContext(rssb.Builder, context.LocalParameters, context.Language); + + if (!this.ResolveStringExpression(headContext, eStr)) + return false; + + var str = rssb.Builder.ToReadOnlySeString(); + var pIdx = 0; + + foreach (var p in str) { - var headContext = new SeStringContext(builder, context.LocalParameters, context.Language); + pIdx++; - if (!this.ResolveStringExpression(headContext, eStr)) - return false; + if (p.Type == ReadOnlySePayloadType.Invalid) + continue; - var str = builder.ToReadOnlySeString(); - var pIdx = 0; - - foreach (var p in str) + if (pIdx == 1 && p.Type == ReadOnlySePayloadType.Text) { - pIdx++; - - if (p.Type == ReadOnlySePayloadType.Invalid) - continue; - - if (pIdx == 1 && p.Type == ReadOnlySePayloadType.Text) - { - context.Builder.Append(Encoding.UTF8.GetString(p.Body.ToArray()).ToUpper(context.CultureInfo)); - continue; - } - - context.Builder.Append(p); + context.Builder.Append(Encoding.UTF8.GetString(p.Body.ToArray()).ToUpper(context.CultureInfo)); + continue; } - return true; - } - finally - { - SeStringBuilder.SharedPool.Return(builder); + context.Builder.Append(p); } + + return true; } private bool TryResolveHead(in SeStringContext context, in ReadOnlySePayloadSpan payload) @@ -1069,40 +1061,33 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator if (!payload.TryGetExpression(out var eStr)) return false; - var builder = SeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); - try + var headContext = new SeStringContext(rssb.Builder, context.LocalParameters, context.Language); + + if (!this.ResolveStringExpression(headContext, eStr)) + return false; + + var str = rssb.Builder.ToReadOnlySeString(); + var pIdx = 0; + + foreach (var p in str) { - var headContext = new SeStringContext(builder, context.LocalParameters, context.Language); + pIdx++; - if (!this.ResolveStringExpression(headContext, eStr)) - return false; + if (p.Type == ReadOnlySePayloadType.Invalid) + continue; - var str = builder.ToReadOnlySeString(); - var pIdx = 0; - - foreach (var p in str) + if (pIdx == 1 && p.Type == ReadOnlySePayloadType.Text) { - pIdx++; - - if (p.Type == ReadOnlySePayloadType.Invalid) - continue; - - if (pIdx == 1 && p.Type == ReadOnlySePayloadType.Text) - { - context.Builder.Append(Encoding.UTF8.GetString(p.Body.Span).FirstCharToUpper(context.CultureInfo)); - continue; - } - - context.Builder.Append(p); + context.Builder.Append(Encoding.UTF8.GetString(p.Body.Span).FirstCharToUpper(context.CultureInfo)); + continue; } - return true; - } - finally - { - SeStringBuilder.SharedPool.Return(builder); + context.Builder.Append(p); } + + return true; } private bool TryResolveSplit(in SeStringContext context, in ReadOnlySePayloadSpan payload) @@ -1113,32 +1098,25 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator if (!eSeparator.TryGetString(out var eSeparatorVal) || !eIndex.TryGetUInt(out var eIndexVal) || eIndexVal <= 0) return false; - var builder = SeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); - try - { - var headContext = new SeStringContext(builder, context.LocalParameters, context.Language); - - if (!this.ResolveStringExpression(headContext, eText)) - return false; - - var separator = eSeparatorVal.ExtractText(); - if (separator.Length < 1) - return false; - - var splitted = builder.ToReadOnlySeString().ExtractText().Split(separator[0]); - if (eIndexVal <= splitted.Length) - { - context.Builder.Append(splitted[eIndexVal - 1]); - return true; - } + var headContext = new SeStringContext(rssb.Builder, context.LocalParameters, context.Language); + if (!this.ResolveStringExpression(headContext, eText)) return false; - } - finally + + var separator = eSeparatorVal.ExtractText(); + if (separator.Length < 1) + return false; + + var splitted = rssb.Builder.ToReadOnlySeString().ExtractText().Split(separator[0]); + if (eIndexVal <= splitted.Length) { - SeStringBuilder.SharedPool.Return(builder); + context.Builder.Append(splitted[eIndexVal - 1]); + return true; } + + return false; } private bool TryResolveHeadAll(in SeStringContext context, in ReadOnlySePayloadSpan payload) @@ -1146,37 +1124,30 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator if (!payload.TryGetExpression(out var eStr)) return false; - var builder = SeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); - try + var headContext = new SeStringContext(rssb.Builder, context.LocalParameters, context.Language); + + if (!this.ResolveStringExpression(headContext, eStr)) + return false; + + var str = rssb.Builder.ToReadOnlySeString(); + + foreach (var p in str) { - var headContext = new SeStringContext(builder, context.LocalParameters, context.Language); + if (p.Type == ReadOnlySePayloadType.Invalid) + continue; - if (!this.ResolveStringExpression(headContext, eStr)) - return false; - - var str = builder.ToReadOnlySeString(); - - foreach (var p in str) + if (p.Type == ReadOnlySePayloadType.Text) { - if (p.Type == ReadOnlySePayloadType.Invalid) - continue; - - if (p.Type == ReadOnlySePayloadType.Text) - { - context.Builder.Append(Encoding.UTF8.GetString(p.Body.Span).ToUpper(true, true, false, context.Language)); - continue; - } - - context.Builder.Append(p); + context.Builder.Append(Encoding.UTF8.GetString(p.Body.Span).ToUpper(true, true, false, context.Language)); + continue; } - return true; - } - finally - { - SeStringBuilder.SharedPool.Return(builder); + context.Builder.Append(p); } + + return true; } private bool TryResolveFixed(in SeStringContext context, in ReadOnlySePayloadSpan payload) @@ -1306,14 +1277,13 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator if (!this.dataManager.GetExcelSheet().TryGetRow(mapId, out var mapRow)) return false; - var sb = SeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); - sb.Append(placeNameRow.Name); + rssb.Builder.Append(placeNameRow.Name); if (instance is > 0 and <= 9) - sb.Append((char)((char)0xE0B0 + (char)instance)); + rssb.Builder.Append((char)((char)0xE0B0 + (char)instance)); - var placeNameWithInstance = sb.ToReadOnlySeString(); - SeStringBuilder.SharedPool.Return(sb); + var placeNameWithInstance = rssb.Builder.ToReadOnlySeString(); var mapPosX = ConvertRawToMapPosX(mapRow, rawX / 1000f); var mapPosY = ConvertRawToMapPosY(mapRow, rawY / 1000f); @@ -1462,23 +1432,22 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator statusDescription = statusRow.Description.AsSpan(); } - var sb = SeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); switch (statusRow.StatusCategory) { case 1: - sb.Append(this.EvaluateFromAddon(376, default, context.Language)); + rssb.Builder.Append(this.EvaluateFromAddon(376, default, context.Language)); break; case 2: - sb.Append(this.EvaluateFromAddon(377, default, context.Language)); + rssb.Builder.Append(this.EvaluateFromAddon(377, default, context.Language)); break; } - sb.Append(statusName); + rssb.Builder.Append(statusName); - var linkText = sb.ToReadOnlySeString(); - SeStringBuilder.SharedPool.Return(sb); + var linkText = rssb.Builder.ToReadOnlySeString(); context.Builder .BeginMacro(MacroCode.Link) @@ -1733,38 +1702,31 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator if (!payload.TryGetExpression(out var eStr)) return false; - var builder = SeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); - try + var headContext = new SeStringContext(rssb.Builder, context.LocalParameters, context.Language); + + if (!this.ResolveStringExpression(headContext, eStr)) + return false; + + var str = rssb.Builder.ToReadOnlySeString(); + + foreach (var p in str) { - var headContext = new SeStringContext(builder, context.LocalParameters, context.Language); + if (p.Type == ReadOnlySePayloadType.Invalid) + continue; - if (!this.ResolveStringExpression(headContext, eStr)) - return false; - - var str = builder.ToReadOnlySeString(); - - foreach (var p in str) + if (p.Type == ReadOnlySePayloadType.Text) { - if (p.Type == ReadOnlySePayloadType.Invalid) - continue; + context.Builder.Append(Encoding.UTF8.GetString(p.Body.ToArray()).ToLower(context.CultureInfo)); - if (p.Type == ReadOnlySePayloadType.Text) - { - context.Builder.Append(Encoding.UTF8.GetString(p.Body.ToArray()).ToLower(context.CultureInfo)); - - continue; - } - - context.Builder.Append(p); + continue; } - return true; - } - finally - { - SeStringBuilder.SharedPool.Return(builder); + context.Builder.Append(p); } + + return true; } private bool TryResolveNoun(ClientLanguage language, in SeStringContext context, in ReadOnlySePayloadSpan payload) @@ -1834,40 +1796,33 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator if (!payload.TryGetExpression(out var eStr)) return false; - var builder = SeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); - try + var headContext = new SeStringContext(rssb.Builder, context.LocalParameters, context.Language); + + if (!this.ResolveStringExpression(headContext, eStr)) + return false; + + var str = rssb.Builder.ToReadOnlySeString(); + var pIdx = 0; + + foreach (var p in str) { - var headContext = new SeStringContext(builder, context.LocalParameters, context.Language); + pIdx++; - if (!this.ResolveStringExpression(headContext, eStr)) - return false; + if (p.Type == ReadOnlySePayloadType.Invalid) + continue; - var str = builder.ToReadOnlySeString(); - var pIdx = 0; - - foreach (var p in str) + if (pIdx == 1 && p.Type == ReadOnlySePayloadType.Text) { - pIdx++; - - if (p.Type == ReadOnlySePayloadType.Invalid) - continue; - - if (pIdx == 1 && p.Type == ReadOnlySePayloadType.Text) - { - context.Builder.Append(Encoding.UTF8.GetString(p.Body.Span).FirstCharToLower(context.CultureInfo)); - continue; - } - - context.Builder.Append(p); + context.Builder.Append(Encoding.UTF8.GetString(p.Body.Span).FirstCharToLower(context.CultureInfo)); + continue; } - return true; - } - finally - { - SeStringBuilder.SharedPool.Return(builder); + context.Builder.Append(p); } + + return true; } private bool TryResolveColorType(in SeStringContext context, in ReadOnlySePayloadSpan payload) @@ -2132,19 +2087,19 @@ internal class SeStringEvaluator : IServiceType, ISeStringEvaluator if (operand1.TryGetString(out var strval1) && operand2.TryGetString(out var strval2)) { + using var rssb1 = new RentedSeStringBuilder(); + using var rssb2 = new RentedSeStringBuilder(); var resolvedStr1 = this.EvaluateAndAppendTo( - SeStringBuilder.SharedPool.Get(), + rssb1.Builder, strval1, context.LocalParameters, context.Language); var resolvedStr2 = this.EvaluateAndAppendTo( - SeStringBuilder.SharedPool.Get(), + rssb2.Builder, strval2, context.LocalParameters, context.Language); var equals = resolvedStr1.GetViewAsSpan().SequenceEqual(resolvedStr2.GetViewAsSpan()); - SeStringBuilder.SharedPool.Return(resolvedStr1); - SeStringBuilder.SharedPool.Return(resolvedStr2); if ((ExpressionType)exprType == ExpressionType.Equal) value = equals ? 1u : 0u; diff --git a/Dalamud/Game/Text/Noun/NounProcessor.cs b/Dalamud/Game/Text/Noun/NounProcessor.cs index 18f8cd4a9..993d341df 100644 --- a/Dalamud/Game/Text/Noun/NounProcessor.cs +++ b/Dalamud/Game/Text/Noun/NounProcessor.cs @@ -9,7 +9,6 @@ using Dalamud.Utility; using Lumina.Excel; using Lumina.Text.ReadOnly; -using LSeStringBuilder = Lumina.Text.SeStringBuilder; using LSheets = Lumina.Excel.Sheets; namespace Dalamud.Game.Text.Noun; @@ -147,30 +146,28 @@ internal class NounProcessor : IServiceType var attributiveSheet = this.dataManager.Excel.GetSheet(nounParams.Language.ToLumina(), nameof(LSheets.Attributive)); - var builder = LSeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); // Ko-So-A-Do var ksad = attributiveSheet.GetRow((uint)nounParams.ArticleType).ReadStringColumn(nounParams.Quantity > 1 ? 1 : 0); if (!ksad.IsEmpty) { - builder.Append(ksad); + rssb.Builder.Append(ksad); if (nounParams.Quantity > 1) { - builder.ReplaceText("[n]"u8, ReadOnlySeString.FromText(nounParams.Quantity.ToString())); + rssb.Builder.ReplaceText("[n]"u8, ReadOnlySeString.FromText(nounParams.Quantity.ToString())); } } if (!nounParams.LinkMarker.IsEmpty) - builder.Append(nounParams.LinkMarker); + rssb.Builder.Append(nounParams.LinkMarker); var text = row.ReadStringColumn(nounParams.ColumnOffset); if (!text.IsEmpty) - builder.Append(text); + rssb.Builder.Append(text); - var ross = builder.ToReadOnlySeString(); - LSeStringBuilder.SharedPool.Return(builder); - return ross; + return rssb.Builder.ToReadOnlySeString(); } /// @@ -200,7 +197,7 @@ internal class NounProcessor : IServiceType var attributiveSheet = this.dataManager.Excel.GetSheet(nounParams.Language.ToLumina(), nameof(LSheets.Attributive)); - var builder = LSeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); var isProperNounColumn = nounParams.ColumnOffset + ArticleColumnIdx; var isProperNoun = isProperNounColumn >= 0 ? row.ReadInt8Column(isProperNounColumn) : ~isProperNounColumn; @@ -216,21 +213,19 @@ internal class NounProcessor : IServiceType var article = attributiveSheet.GetRow((uint)nounParams.ArticleType) .ReadStringColumn(articleColumn + grammaticalNumberColumnOffset); if (!article.IsEmpty) - builder.Append(article); + rssb.Builder.Append(article); if (!nounParams.LinkMarker.IsEmpty) - builder.Append(nounParams.LinkMarker); + rssb.Builder.Append(nounParams.LinkMarker); } var text = row.ReadStringColumn(nounParams.ColumnOffset + (nounParams.Quantity == 1 ? SingularColumnIdx : PluralColumnIdx)); if (!text.IsEmpty) - builder.Append(text); + rssb.Builder.Append(text); - builder.ReplaceText("[n]"u8, ReadOnlySeString.FromText(nounParams.Quantity.ToString())); + rssb.Builder.ReplaceText("[n]"u8, ReadOnlySeString.FromText(nounParams.Quantity.ToString())); - var ross = builder.ToReadOnlySeString(); - LSeStringBuilder.SharedPool.Return(builder); - return ross; + return rssb.Builder.ToReadOnlySeString(); } /// @@ -262,17 +257,13 @@ internal class NounProcessor : IServiceType var attributiveSheet = this.dataManager.Excel.GetSheet(nounParams.Language.ToLumina(), nameof(LSheets.Attributive)); - var builder = LSeStringBuilder.SharedPool.Get(); - ReadOnlySeString ross; + using var rssb = new RentedSeStringBuilder(); if (nounParams.IsActionSheet) { - builder.Append(row.ReadStringColumn(nounParams.GrammaticalCase)); - builder.ReplaceText("[n]"u8, ReadOnlySeString.FromText(nounParams.Quantity.ToString())); - - ross = builder.ToReadOnlySeString(); - LSeStringBuilder.SharedPool.Return(builder); - return ross; + rssb.Builder.Append(row.ReadStringColumn(nounParams.GrammaticalCase)); + rssb.Builder.ReplaceText("[n]"u8, ReadOnlySeString.FromText(nounParams.Quantity.ToString())); + return rssb.Builder.ToReadOnlySeString(); } var genderIndexColumn = nounParams.ColumnOffset + PronounColumnIdx; @@ -302,35 +293,32 @@ internal class NounProcessor : IServiceType var grammaticalGender = attributiveSheet.GetRow((uint)nounParams.ArticleType) .ReadStringColumn(caseColumnOffset + genderIndex); // Genus if (!grammaticalGender.IsEmpty) - builder.Append(grammaticalGender); + rssb.Builder.Append(grammaticalGender); } if (!nounParams.LinkMarker.IsEmpty) - builder.Append(nounParams.LinkMarker); + rssb.Builder.Append(nounParams.LinkMarker); - builder.Append(text); + rssb.Builder.Append(text); var plural = attributiveSheet.GetRow((uint)(caseRowOffset + 26)) .ReadStringColumn(caseColumnOffset + genderIndex); - if (builder.ContainsText("[p]"u8)) - builder.ReplaceText("[p]"u8, plural); + if (rssb.Builder.ContainsText("[p]"u8)) + rssb.Builder.ReplaceText("[p]"u8, plural); else - builder.Append(plural); + rssb.Builder.Append(plural); if (hasT) { var article = attributiveSheet.GetRow(39).ReadStringColumn(caseColumnOffset + genderIndex); // Definiter Artikel - builder.ReplaceText("[t]"u8, article); + rssb.Builder.ReplaceText("[t]"u8, article); } } - var pa = attributiveSheet.GetRow(24).ReadStringColumn(caseColumnOffset + genderIndex); - builder.ReplaceText("[pa]"u8, pa); + rssb.Builder.ReplaceText("[pa]"u8, attributiveSheet.GetRow(24).ReadStringColumn(caseColumnOffset + genderIndex)); - RawRow declensionRow; - - declensionRow = (GermanArticleType)nounParams.ArticleType switch + var declensionRow = (GermanArticleType)nounParams.ArticleType switch { // Schwache Flexion eines Adjektivs?! GermanArticleType.Possessive or GermanArticleType.Demonstrative => attributiveSheet.GetRow(25), @@ -347,14 +335,10 @@ internal class NounProcessor : IServiceType _ => attributiveSheet.GetRow(26), }; - var declension = declensionRow.ReadStringColumn(caseColumnOffset + genderIndex); - builder.ReplaceText("[a]"u8, declension); + rssb.Builder.ReplaceText("[a]"u8, declensionRow.ReadStringColumn(caseColumnOffset + genderIndex)); + rssb.Builder.ReplaceText("[n]"u8, ReadOnlySeString.FromText(nounParams.Quantity.ToString())); - builder.ReplaceText("[n]"u8, ReadOnlySeString.FromText(nounParams.Quantity.ToString())); - - ross = builder.ToReadOnlySeString(); - LSeStringBuilder.SharedPool.Return(builder); - return ross; + return rssb.Builder.ToReadOnlySeString(); } /// @@ -385,8 +369,7 @@ internal class NounProcessor : IServiceType var attributiveSheet = this.dataManager.Excel.GetSheet(nounParams.Language.ToLumina(), nameof(LSheets.Attributive)); - var builder = LSeStringBuilder.SharedPool.Get(); - ReadOnlySeString ross; + using var rssb = new RentedSeStringBuilder(); var startsWithVowelColumn = nounParams.ColumnOffset + StartsWithVowelColumnIdx; var startsWithVowel = startsWithVowelColumn >= 0 @@ -405,21 +388,19 @@ internal class NounProcessor : IServiceType { var v21 = attributiveSheet.GetRow((uint)nounParams.ArticleType).ReadStringColumn(v20); if (!v21.IsEmpty) - builder.Append(v21); + rssb.Builder.Append(v21); if (!nounParams.LinkMarker.IsEmpty) - builder.Append(nounParams.LinkMarker); + rssb.Builder.Append(nounParams.LinkMarker); var text = row.ReadStringColumn(nounParams.ColumnOffset + (nounParams.Quantity <= 1 ? SingularColumnIdx : PluralColumnIdx)); if (!text.IsEmpty) - builder.Append(text); + rssb.Builder.Append(text); if (nounParams.Quantity <= 1) - builder.ReplaceText("[n]"u8, ReadOnlySeString.FromText(nounParams.Quantity.ToString())); + rssb.Builder.ReplaceText("[n]"u8, ReadOnlySeString.FromText(nounParams.Quantity.ToString())); - ross = builder.ToReadOnlySeString(); - LSeStringBuilder.SharedPool.Return(builder); - return ross; + return rssb.Builder.ToReadOnlySeString(); } var v17 = row.ReadInt8Column(nounParams.ColumnOffset + Unknown5ColumnIdx); @@ -428,34 +409,32 @@ internal class NounProcessor : IServiceType var v29 = attributiveSheet.GetRow((uint)nounParams.ArticleType).ReadStringColumn(v20 + 2); if (!v29.IsEmpty) { - builder.Append(v29); + rssb.Builder.Append(v29); if (!nounParams.LinkMarker.IsEmpty) - builder.Append(nounParams.LinkMarker); + rssb.Builder.Append(nounParams.LinkMarker); var text = row.ReadStringColumn(nounParams.ColumnOffset + PluralColumnIdx); if (!text.IsEmpty) - builder.Append(text); + rssb.Builder.Append(text); } } else { var v27 = attributiveSheet.GetRow((uint)nounParams.ArticleType).ReadStringColumn(v20 + (v17 != 0 ? 1 : 3)); if (!v27.IsEmpty) - builder.Append(v27); + rssb.Builder.Append(v27); if (!nounParams.LinkMarker.IsEmpty) - builder.Append(nounParams.LinkMarker); + rssb.Builder.Append(nounParams.LinkMarker); var text = row.ReadStringColumn(nounParams.ColumnOffset + SingularColumnIdx); if (!text.IsEmpty) - builder.Append(text); + rssb.Builder.Append(text); } - builder.ReplaceText("[n]"u8, ReadOnlySeString.FromText(nounParams.Quantity.ToString())); + rssb.Builder.ReplaceText("[n]"u8, ReadOnlySeString.FromText(nounParams.Quantity.ToString())); - ross = builder.ToReadOnlySeString(); - LSeStringBuilder.SharedPool.Return(builder); - return ross; + return rssb.Builder.ToReadOnlySeString(); } } diff --git a/Dalamud/Game/Text/SeStringHandling/Payloads/AutoTranslatePayload.cs b/Dalamud/Game/Text/SeStringHandling/Payloads/AutoTranslatePayload.cs index 470e942c3..8178a6d33 100644 --- a/Dalamud/Game/Text/SeStringHandling/Payloads/AutoTranslatePayload.cs +++ b/Dalamud/Game/Text/SeStringHandling/Payloads/AutoTranslatePayload.cs @@ -1,6 +1,7 @@ using System.IO; using Dalamud.Game.Text.Evaluator; +using Dalamud.Utility; using Lumina.Text.Payloads; using Lumina.Text.ReadOnly; @@ -32,13 +33,14 @@ public class AutoTranslatePayload : Payload, ITextProvider this.Group = group; this.Key = key; - var ssb = Lumina.Text.SeStringBuilder.SharedPool.Get(); - this.payload = ssb.BeginMacro(MacroCode.Fixed) - .AppendUIntExpression(group - 1) - .AppendUIntExpression(key) - .EndMacro() - .ToReadOnlySeString(); - Lumina.Text.SeStringBuilder.SharedPool.Return(ssb); + using var rssb = new RentedSeStringBuilder(); + + this.payload = rssb.Builder + .BeginMacro(MacroCode.Fixed) + .AppendUIntExpression(group - 1) + .AppendUIntExpression(key) + .EndMacro() + .ToReadOnlySeString(); } /// diff --git a/Dalamud/Game/Text/SeStringHandling/Payloads/DalamudLinkPayload.cs b/Dalamud/Game/Text/SeStringHandling/Payloads/DalamudLinkPayload.cs index 8b020b111..2becb815b 100644 --- a/Dalamud/Game/Text/SeStringHandling/Payloads/DalamudLinkPayload.cs +++ b/Dalamud/Game/Text/SeStringHandling/Payloads/DalamudLinkPayload.cs @@ -1,5 +1,7 @@ using System.IO; +using Dalamud.Utility; + using Lumina.Text.Payloads; using Lumina.Text.ReadOnly; @@ -37,19 +39,18 @@ public class DalamudLinkPayload : Payload /// protected override byte[] EncodeImpl() { - var ssb = Lumina.Text.SeStringBuilder.SharedPool.Get(); - var res = ssb.BeginMacro(MacroCode.Link) - .AppendIntExpression((int)EmbeddedInfoType.DalamudLink - 1) - .AppendUIntExpression(this.CommandId) - .AppendIntExpression(this.Extra1) - .AppendIntExpression(this.Extra2) - .BeginStringExpression() - .Append(JsonConvert.SerializeObject(new[] { this.Plugin, this.ExtraString })) - .EndExpression() - .EndMacro() - .ToArray(); - Lumina.Text.SeStringBuilder.SharedPool.Return(ssb); - return res; + using var rssb = new RentedSeStringBuilder(); + return rssb.Builder + .BeginMacro(MacroCode.Link) + .AppendIntExpression((int)EmbeddedInfoType.DalamudLink - 1) + .AppendUIntExpression(this.CommandId) + .AppendIntExpression(this.Extra1) + .AppendIntExpression(this.Extra2) + .BeginStringExpression() + .Append(JsonConvert.SerializeObject(new[] { this.Plugin, this.ExtraString })) + .EndExpression() + .EndMacro() + .ToArray(); } /// diff --git a/Dalamud/Game/Text/SeStringHandling/Payloads/PlayerPayload.cs b/Dalamud/Game/Text/SeStringHandling/Payloads/PlayerPayload.cs index 55697782e..01ca1b955 100644 --- a/Dalamud/Game/Text/SeStringHandling/Payloads/PlayerPayload.cs +++ b/Dalamud/Game/Text/SeStringHandling/Payloads/PlayerPayload.cs @@ -1,8 +1,7 @@ -using System.Collections.Generic; using System.IO; -using System.Text; using Dalamud.Data; +using Dalamud.Utility; using Lumina.Excel; using Lumina.Excel.Sheets; @@ -87,14 +86,12 @@ public class PlayerPayload : Payload /// protected override byte[] EncodeImpl() { - var ssb = Lumina.Text.SeStringBuilder.SharedPool.Get(); - var res = ssb - .PushLinkCharacter(this.playerName, this.serverId) - .Append(this.playerName) - .PopLink() - .ToArray(); - Lumina.Text.SeStringBuilder.SharedPool.Return(ssb); - return res; + using var rssb = new RentedSeStringBuilder(); + return rssb.Builder + .PushLinkCharacter(this.playerName, this.serverId) + .Append(this.playerName) + .PopLink() + .ToArray(); } /// diff --git a/Dalamud/Game/Text/SeStringHandling/SeString.cs b/Dalamud/Game/Text/SeStringHandling/SeString.cs index a1ef5e936..ca14299db 100644 --- a/Dalamud/Game/Text/SeStringHandling/SeString.cs +++ b/Dalamud/Game/Text/SeStringHandling/SeString.cs @@ -198,8 +198,9 @@ public class SeString var textColor = ItemUtil.GetItemRarityColorType(rawId); var textEdgeColor = textColor + 1u; - var sb = LSeStringBuilder.SharedPool.Get(); - var itemLink = sb + using var rssb = new RentedSeStringBuilder(); + + var itemLink = rssb.Builder .PushColorType(textColor) .PushEdgeColorType(textEdgeColor) .PushLinkItem(rawId, copyName) @@ -208,7 +209,6 @@ public class SeString .PopEdgeColorType() .PopColorType() .ToReadOnlySeString(); - LSeStringBuilder.SharedPool.Return(sb); return SeString.Parse(seStringEvaluator.EvaluateFromAddon(371, [itemLink], clientState.ClientLanguage)); } diff --git a/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringCreatorWidget.cs b/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringCreatorWidget.cs index e9b4022e4..d43d3b7b2 100644 --- a/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringCreatorWidget.cs +++ b/Dalamud/Interface/Internal/Windows/Data/Widgets/SeStringCreatorWidget.cs @@ -29,8 +29,6 @@ using Lumina.Text.Expressions; using Lumina.Text.Payloads; using Lumina.Text.ReadOnly; -using LSeStringBuilder = Lumina.Text.SeStringBuilder; - namespace Dalamud.Interface.Internal.Windows.Data.Widgets; /// @@ -474,25 +472,25 @@ internal class SeStringCreatorWidget : IDataWindowWidget if (ImGui.Button("Print Evaluated"u8)) { - var sb = new LSeStringBuilder(); + using var rssb = new RentedSeStringBuilder(); foreach (var entry in this.entries) { switch (entry.Type) { case TextEntryType.String: - sb.Append(entry.Message); + rssb.Builder.Append(entry.Message); break; case TextEntryType.Macro: case TextEntryType.Fixed: - sb.AppendMacroString(entry.Message); + rssb.Builder.AppendMacroString(entry.Message); break; } } var evaluated = Service.Get().Evaluate( - sb.ToReadOnlySeString(), + rssb.Builder.ToReadOnlySeString(), this.localParameters, this.language); @@ -505,24 +503,24 @@ internal class SeStringCreatorWidget : IDataWindowWidget if (ImGui.Button("Copy MacroString"u8)) { - var sb = new LSeStringBuilder(); + using var rssb = new RentedSeStringBuilder(); foreach (var entry in this.entries) { switch (entry.Type) { case TextEntryType.String: - sb.Append(entry.Message); + rssb.Builder.Append(entry.Message); break; case TextEntryType.Macro: case TextEntryType.Fixed: - sb.AppendMacroString(entry.Message); + rssb.Builder.AppendMacroString(entry.Message); break; } } - ImGui.SetClipboardText(sb.ToReadOnlySeString().ToMacroString()); + ImGui.SetClipboardText(rssb.Builder.ToReadOnlySeString().ToMacroString()); } ImGui.SameLine(); @@ -802,24 +800,24 @@ internal class SeStringCreatorWidget : IDataWindowWidget private unsafe void UpdateInputString(bool resetLocalParameters = true) { - var sb = new LSeStringBuilder(); + using var rssb = new RentedSeStringBuilder(); foreach (var entry in this.entries) { switch (entry.Type) { case TextEntryType.String: - sb.Append(entry.Message); + rssb.Builder.Append(entry.Message); break; case TextEntryType.Macro: case TextEntryType.Fixed: - sb.AppendMacroString(entry.Message); + rssb.Builder.AppendMacroString(entry.Message); break; } } - this.input = sb.ToReadOnlySeString(); + this.input = rssb.Builder.ToReadOnlySeString(); if (resetLocalParameters) this.localParameters = null; @@ -998,10 +996,9 @@ internal class SeStringCreatorWidget : IDataWindowWidget } } - var builder = LSeStringBuilder.SharedPool.Get(); - builder.AppendIcon(iconId); - ImGuiHelpers.SeStringWrapped(builder.ToArray()); - LSeStringBuilder.SharedPool.Return(builder); + using var rssb = new RentedSeStringBuilder(); + rssb.Builder.AppendIcon(iconId); + ImGuiHelpers.SeStringWrapped(rssb.Builder.ToArray()); ImGui.SameLine(); } diff --git a/Dalamud/Interface/Internal/Windows/SelfTest/Steps/GamepadStateSelfTestStep.cs b/Dalamud/Interface/Internal/Windows/SelfTest/Steps/GamepadStateSelfTestStep.cs index d272032e7..e2ee676df 100644 --- a/Dalamud/Interface/Internal/Windows/SelfTest/Steps/GamepadStateSelfTestStep.cs +++ b/Dalamud/Interface/Internal/Windows/SelfTest/Steps/GamepadStateSelfTestStep.cs @@ -3,9 +3,9 @@ using System.Linq; using Dalamud.Game.ClientState.GamePad; using Dalamud.Interface.Utility; using Dalamud.Plugin.SelfTest; -using Lumina.Text.Payloads; +using Dalamud.Utility; -using LSeStringBuilder = Lumina.Text.SeStringBuilder; +using Lumina.Text.Payloads; namespace Dalamud.Interface.Internal.Windows.SelfTest.Steps; @@ -29,25 +29,25 @@ internal class GamepadStateSelfTestStep : ISelfTestStep (GamepadButtons.L1, 12), }; - var builder = LSeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); - builder.Append("Hold down "); + rssb.Builder.Append("Hold down "); for (var i = 0; i < buttons.Length; i++) { var (button, iconId) = buttons[i]; - builder.BeginMacro(MacroCode.Icon).AppendUIntExpression(iconId).EndMacro(); - builder.PushColorRgba(gamepadState.Raw(button) == 1 ? 0x0000FF00u : 0x000000FF); - builder.Append(button.ToString()); - builder.PopColor(); - - builder.Append(i < buttons.Length - 1 ? ", " : "."); + rssb.Builder + .BeginMacro(MacroCode.Icon) + .AppendUIntExpression(iconId) + .EndMacro() + .PushColorRgba(gamepadState.Raw(button) == 1 ? 0x0000FF00u : 0x000000FF) + .Append(button.ToString()) + .PopColor() + .Append(i < buttons.Length - 1 ? ", " : "."); } - ImGuiHelpers.SeStringWrapped(builder.ToReadOnlySeString()); - - LSeStringBuilder.SharedPool.Return(builder); + ImGuiHelpers.SeStringWrapped(rssb.Builder.ToReadOnlySeString()); if (buttons.All(tuple => gamepadState.Raw(tuple.Button) == 1)) { diff --git a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs index f826da622..ec9440e0e 100644 --- a/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs +++ b/Dalamud/Interface/Internal/Windows/TitleScreenMenuWindow.cs @@ -26,8 +26,6 @@ using FFXIVClientStructs.FFXIV.Component.GUI; using Lumina.Text.ReadOnly; using Serilog; -using LSeStringBuilder = Lumina.Text.SeStringBuilder; - namespace Dalamud.Interface.Internal.Windows; /// @@ -498,20 +496,23 @@ internal class TitleScreenMenuWindow : Window, IDisposable return; this.lastLoadedPluginCount = count; - var lssb = LSeStringBuilder.SharedPool.Get(); - lssb.Append(new ReadOnlySeStringSpan(addon->AtkValues[1].String.Value)).Append("\n\n"); - lssb.PushEdgeColorType(701).PushColorType(539) - .Append(SeIconChar.BoxedLetterD.ToIconChar()) - .PopColorType().PopEdgeColorType(); - lssb.Append($" Dalamud: {Versioning.GetScmVersion()}"); + using var rssb = new RentedSeStringBuilder(); - lssb.Append($" - {count} {(count != 1 ? "plugins" : "plugin")} loaded"); + rssb.Builder + .Append(new ReadOnlySeStringSpan(addon->AtkValues[1].String.Value)) + .Append("\n\n") + .PushEdgeColorType(701) + .PushColorType(539) + .Append(SeIconChar.BoxedLetterD.ToIconChar()) + .PopColorType() + .PopEdgeColorType() + .Append($" Dalamud: {Versioning.GetScmVersion()}") + .Append($" - {count} {(count != 1 ? "plugins" : "plugin")} loaded"); if (pm?.SafeMode is true) - lssb.PushColorType(17).Append(" [SAFE MODE]").PopColorType(); + rssb.Builder.PushColorType(17).Append(" [SAFE MODE]").PopColorType(); - textNode->SetText(lssb.GetViewAsSpan()); - LSeStringBuilder.SharedPool.Return(lssb); + textNode->SetText(rssb.Builder.GetViewAsSpan()); } private void TitleScreenMenuEntryListChange() => this.privateAtlas.BuildFontsAsync(); diff --git a/Dalamud/Utility/ItemUtil.cs b/Dalamud/Utility/ItemUtil.cs index b632d14d7..8ee465486 100644 --- a/Dalamud/Utility/ItemUtil.cs +++ b/Dalamud/Utility/ItemUtil.cs @@ -5,7 +5,6 @@ using Dalamud.Game; using Dalamud.Game.Text; using Lumina.Excel.Sheets; -using Lumina.Text; using Lumina.Text.ReadOnly; namespace Dalamud.Utility; @@ -150,23 +149,21 @@ public static class ItemUtil if (!includeIcon || kind is not (ItemKind.Hq or ItemKind.Collectible)) return item.Name; - var builder = SeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); - builder.Append(item.Name); + rssb.Builder.Append(item.Name); switch (kind) { case ItemKind.Hq: - builder.Append($" {(char)SeIconChar.HighQuality}"); + rssb.Builder.Append($" {(char)SeIconChar.HighQuality}"); break; case ItemKind.Collectible: - builder.Append($" {(char)SeIconChar.Collectible}"); + rssb.Builder.Append($" {(char)SeIconChar.Collectible}"); break; } - var itemName = builder.ToReadOnlySeString(); - SeStringBuilder.SharedPool.Return(builder); - return itemName; + return rssb.Builder.ToReadOnlySeString(); } /// diff --git a/Dalamud/Utility/SeStringExtensions.cs b/Dalamud/Utility/SeStringExtensions.cs index cd095c467..9de116f26 100644 --- a/Dalamud/Utility/SeStringExtensions.cs +++ b/Dalamud/Utility/SeStringExtensions.cs @@ -1,7 +1,3 @@ -using System.Linq; - -using InteropGenerator.Runtime; - using Lumina.Text.Parse; using Lumina.Text.ReadOnly; @@ -49,11 +45,9 @@ public static class SeStringExtensions /// this for method chaining. public static DSeStringBuilder AppendMacroString(this DSeStringBuilder ssb, ReadOnlySpan macroString) { - var lssb = LSeStringBuilder.SharedPool.Get(); - lssb.AppendMacroString(macroString, new() { ExceptionMode = MacroStringParseExceptionMode.EmbedError }); - ssb.Append(DSeString.Parse(lssb.ToReadOnlySeString().Data.Span)); - LSeStringBuilder.SharedPool.Return(lssb); - return ssb; + using var rssb = new RentedSeStringBuilder(); + rssb.Builder.AppendMacroString(macroString, new() { ExceptionMode = MacroStringParseExceptionMode.EmbedError }); + return ssb.Append(DSeString.Parse(rssb.Builder.ToReadOnlySeString().Data.Span)); } /// Compiles and appends a macro string. @@ -62,11 +56,9 @@ public static class SeStringExtensions /// this for method chaining. public static DSeStringBuilder AppendMacroString(this DSeStringBuilder ssb, ReadOnlySpan macroString) { - var lssb = LSeStringBuilder.SharedPool.Get(); - lssb.AppendMacroString(macroString, new() { ExceptionMode = MacroStringParseExceptionMode.EmbedError }); - ssb.Append(DSeString.Parse(lssb.ToReadOnlySeString().Data.Span)); - LSeStringBuilder.SharedPool.Return(lssb); - return ssb; + using var rssb = new RentedSeStringBuilder(); + rssb.Builder.AppendMacroString(macroString, new() { ExceptionMode = MacroStringParseExceptionMode.EmbedError }); + return ssb.Append(DSeString.Parse(rssb.Builder.ToReadOnlySeString().Data.Span)); } /// @@ -163,7 +155,7 @@ public static class SeStringExtensions if (ross.IsEmpty) return ross; - var sb = LSeStringBuilder.SharedPool.Get(); + using var rssb = new RentedSeStringBuilder(); foreach (var payload in ross) { @@ -172,25 +164,25 @@ public static class SeStringExtensions if (payload.Type != ReadOnlySePayloadType.Text) { - sb.Append(payload); + rssb.Builder.Append(payload); continue; } var index = payload.Body.Span.IndexOf(toFind); if (index == -1) { - sb.Append(payload); + rssb.Builder.Append(payload); continue; } var lastIndex = 0; while (index != -1) { - sb.Append(payload.Body.Span[lastIndex..index]); + rssb.Builder.Append(payload.Body.Span[lastIndex..index]); if (!replacement.IsEmpty) { - sb.Append(replacement); + rssb.Builder.Append(replacement); } lastIndex = index + toFind.Length; @@ -200,12 +192,10 @@ public static class SeStringExtensions index += lastIndex; } - sb.Append(payload.Body.Span[lastIndex..]); + rssb.Builder.Append(payload.Body.Span[lastIndex..]); } - var output = sb.ToReadOnlySeString(); - LSeStringBuilder.SharedPool.Return(sb); - return output; + return rssb.Builder.ToReadOnlySeString(); } ///