/*************************************************************************
* ModernUO *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: LocalizationEntry.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see . *
*************************************************************************/
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using Server.Buffers;
using Server.Collections;
namespace Server;
public class LocalizationEntry
{
private static readonly Regex _textRegex = new(
@"~(\d+)[_\w]+~",
RegexOptions.Compiled |
RegexOptions.IgnoreCase |
RegexOptions.Singleline |
RegexOptions.CultureInvariant
);
public string Language { get; }
public int Number { get; }
public string Text { get; }
public string[] TextSlices { get; }
public string StringFormatter { get; }
public LocalizationEntry(string lang, int number, string text)
{
Language = lang;
Number = number;
Text = text;
ParseText(text, out var textSlices, out var stringFormatter);
TextSlices = textSlices;
StringFormatter = stringFormatter;
}
private static void ParseText(string text, out string[] textSlices, out string stringFormatter)
{
bool hasMatch = false;
var prevIndex = 0;
var builder = new ValueStringBuilder(stackalloc char[256]);
using var queue = PooledRefQueue.Create();
foreach (Match match in _textRegex.Matches(text))
{
if (prevIndex < match.Index)
{
var substr = text[prevIndex..match.Index];
builder.Append(substr);
queue.Enqueue(substr);
}
queue.Enqueue(null);
hasMatch = true;
builder.Append($"{{{int.Parse(match.Groups[1].Value) - 1}}}");
prevIndex = match.Index + match.Length;
}
if (prevIndex < text.Length - 1)
{
var substr = prevIndex == 0 ? text : text[prevIndex..];
builder.Append(substr);
queue.Enqueue(substr);
}
textSlices = queue.ToArray();
stringFormatter = hasMatch ? builder.ToString() : null;
builder.Dispose();
}
public string Format(params object[] args) => string.Format(StringFormatter, args);
///
/// Creates a formatted string of the localization entry.
/// Uses string interpolation under the hood. This method is preferably relative to the object array method signature.
/// Example:
/// Format($"{totalItems}{maxItems}{totalWeight}");
///
/// interpolated string handler used by the compiler as a string builder during compilation
/// A copy of the localization text where the placeholder arguments have been replaced with string representations of the provided interpolation arguments
public PooledArraySpanFormattable Format(
[InterpolatedStringHandlerArgument("")]
ref LocalizationInterpolationHandler handler
)
{
var chars = handler.ToPooledArray(out var length);
handler = default; // Defensive clear
return new PooledArraySpanFormattable(chars, length);
}
}