Use RentedSeStringBuilder more

This commit is contained in:
Haselnussbomber 2025-12-19 17:34:42 +01:00
parent 5e4ad4a694
commit a3d930b8e2
No known key found for this signature in database
GPG key ID: BB905BB49E7295D1
13 changed files with 275 additions and 367 deletions

View file

@ -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<byte> 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);
}
/// <summary>
@ -326,29 +323,28 @@ internal sealed unsafe class ChatGui : IInternalDisposableService, IChatGui
private void PrintTagged(ReadOnlySpan<byte> 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);
}
}
}

View file

@ -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;
/// <summary>
@ -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);
}

View file

@ -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<Lumina.Excel.Sheets.Map>().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;

View file

@ -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<RawRow>(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();
}
/// <summary>
@ -200,7 +197,7 @@ internal class NounProcessor : IServiceType
var attributiveSheet = this.dataManager.Excel.GetSheet<RawRow>(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();
}
/// <summary>
@ -262,17 +257,13 @@ internal class NounProcessor : IServiceType
var attributiveSheet = this.dataManager.Excel.GetSheet<RawRow>(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();
}
/// <summary>
@ -385,8 +369,7 @@ internal class NounProcessor : IServiceType
var attributiveSheet = this.dataManager.Excel.GetSheet<RawRow>(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();
}
}

View file

@ -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();
}
/// <summary>

View file

@ -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
/// <inheritdoc/>
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();
}
/// <inheritdoc/>

View file

@ -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
/// <inheritdoc/>
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();
}
/// <inheritdoc/>

View file

@ -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));
}

View file

@ -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;
/// <summary>
@ -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<SeStringEvaluator>.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();
}

View file

@ -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))
{

View file

@ -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;
/// <summary>
@ -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();

View file

@ -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();
}
/// <summary>

View file

@ -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
/// <returns><c>this</c> for method chaining.</returns>
public static DSeStringBuilder AppendMacroString(this DSeStringBuilder ssb, ReadOnlySpan<byte> 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));
}
/// <summary>Compiles and appends a macro string.</summary>
@ -62,11 +56,9 @@ public static class SeStringExtensions
/// <returns><c>this</c> for method chaining.</returns>
public static DSeStringBuilder AppendMacroString(this DSeStringBuilder ssb, ReadOnlySpan<char> 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));
}
/// <summary>
@ -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();
}
/// <summary>