Cache regex instances in most cases (#27699)
Using static Regex functions that take in a pattern is bad because the pattern constantly needs to be re-parsed. With https://github.com/space-wizards/RobustToolbox/pull/5107, the engine has an analyzer to warn for this practice now. This commit brings most of content up to snuff already, though some of the tricker code I left for somebody else.
This commit is contained in:
committed by
GitHub
parent
70d3cf7ba4
commit
4a2a63a86b
@@ -10,6 +10,10 @@ public sealed class FrenchAccentSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ReplacementAccentSystem _replacement = default!;
|
||||
|
||||
private static readonly Regex RegexTh = new(@"th", RegexOptions.IgnoreCase);
|
||||
private static readonly Regex RegexStartH = new(@"(?<!\w)h", RegexOptions.IgnoreCase);
|
||||
private static readonly Regex RegexSpacePunctuation = new(@"(?<=\w\w)[!?;:](?!\w)", RegexOptions.IgnoreCase);
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -23,17 +27,14 @@ public sealed class FrenchAccentSystem : EntitySystem
|
||||
|
||||
msg = _replacement.ApplyReplacements(msg, "french");
|
||||
|
||||
// replaces th with dz
|
||||
msg = Regex.Replace(msg, @"th", "'z", RegexOptions.IgnoreCase);
|
||||
// replaces th with dz
|
||||
msg = RegexTh.Replace(msg, "'z");
|
||||
|
||||
// removes the letter h from the start of words.
|
||||
msg = Regex.Replace(msg, @"(?<!\w)[h]", "'", RegexOptions.IgnoreCase);
|
||||
msg = RegexStartH.Replace(msg, "'");
|
||||
|
||||
// spaces out ! ? : and ;.
|
||||
msg = Regex.Replace(msg, @"(?<=\w\w)!(?!\w)", " !", RegexOptions.IgnoreCase);
|
||||
msg = Regex.Replace(msg, @"(?<=\w\w)[?](?!\w)", " ?", RegexOptions.IgnoreCase);
|
||||
msg = Regex.Replace(msg, @"(?<=\w\w)[;](?!\w)", " ;", RegexOptions.IgnoreCase);
|
||||
msg = Regex.Replace(msg, @"(?<=\w\w)[:](?!\w)", " :", RegexOptions.IgnoreCase);
|
||||
msg = RegexSpacePunctuation.Replace(msg, " $&");
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,13 @@ namespace Content.Server.Speech.EntitySystems;
|
||||
|
||||
public sealed class FrontalLispSystem : EntitySystem
|
||||
{
|
||||
// @formatter:off
|
||||
private static readonly Regex RegexUpperTh = new(@"[T]+[Ss]+|[S]+[Cc]+(?=[IiEeYy]+)|[C]+(?=[IiEeYy]+)|[P][Ss]+|([S]+[Tt]+|[T]+)(?=[Ii]+[Oo]+[Uu]*[Nn]*)|[C]+[Hh]+(?=[Ii]*[Ee]*)|[Z]+|[S]+|[X]+(?=[Ee]+)");
|
||||
private static readonly Regex RegexLowerTh = new(@"[t]+[s]+|[s]+[c]+(?=[iey]+)|[c]+(?=[iey]+)|[p][s]+|([s]+[t]+|[t]+)(?=[i]+[o]+[u]*[n]*)|[c]+[h]+(?=[i]*[e]*)|[z]+|[s]+|[x]+(?=[e]+)");
|
||||
private static readonly Regex RegexUpperEcks = new(@"[E]+[Xx]+[Cc]*|[X]+");
|
||||
private static readonly Regex RegexLowerEcks = new(@"[e]+[x]+[c]*|[x]+");
|
||||
// @formatter:on
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -16,11 +23,11 @@ public sealed class FrontalLispSystem : EntitySystem
|
||||
var message = args.Message;
|
||||
|
||||
// handles ts, sc(i|e|y), c(i|e|y), ps, st(io(u|n)), ch(i|e), z, s
|
||||
message = Regex.Replace(message, @"[T]+[Ss]+|[S]+[Cc]+(?=[IiEeYy]+)|[C]+(?=[IiEeYy]+)|[P][Ss]+|([S]+[Tt]+|[T]+)(?=[Ii]+[Oo]+[Uu]*[Nn]*)|[C]+[Hh]+(?=[Ii]*[Ee]*)|[Z]+|[S]+|[X]+(?=[Ee]+)", "TH");
|
||||
message = Regex.Replace(message, @"[t]+[s]+|[s]+[c]+(?=[iey]+)|[c]+(?=[iey]+)|[p][s]+|([s]+[t]+|[t]+)(?=[i]+[o]+[u]*[n]*)|[c]+[h]+(?=[i]*[e]*)|[z]+|[s]+|[x]+(?=[e]+)", "th");
|
||||
message = RegexUpperTh.Replace(message, "TH");
|
||||
message = RegexLowerTh.Replace(message, "th");
|
||||
// handles ex(c), x
|
||||
message = Regex.Replace(message, @"[E]+[Xx]+[Cc]*|[X]+", "EKTH");
|
||||
message = Regex.Replace(message, @"[e]+[x]+[c]*|[x]+", "ekth");
|
||||
message = RegexUpperEcks.Replace(message, "EKTH");
|
||||
message = RegexLowerEcks.Replace(message, "ekth");
|
||||
|
||||
args.Message = message;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,12 @@ namespace Content.Server.Speech.EntitySystems;
|
||||
|
||||
public sealed class LizardAccentSystem : EntitySystem
|
||||
{
|
||||
private static readonly Regex RegexLowerS = new("s+");
|
||||
private static readonly Regex RegexUpperS = new("S+");
|
||||
private static readonly Regex RegexInternalX = new(@"(\w)x");
|
||||
private static readonly Regex RegexLowerEndX = new(@"\bx([\-|r|R]|\b)");
|
||||
private static readonly Regex RegexUpperEndX = new(@"\bX([\-|r|R]|\b)");
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -16,15 +22,15 @@ public sealed class LizardAccentSystem : EntitySystem
|
||||
var message = args.Message;
|
||||
|
||||
// hissss
|
||||
message = Regex.Replace(message, "s+", "sss");
|
||||
message = RegexLowerS.Replace(message, "sss");
|
||||
// hiSSS
|
||||
message = Regex.Replace(message, "S+", "SSS");
|
||||
message = RegexUpperS.Replace(message, "SSS");
|
||||
// ekssit
|
||||
message = Regex.Replace(message, @"(\w)x", "$1kss");
|
||||
message = RegexInternalX.Replace(message, "$1kss");
|
||||
// ecks
|
||||
message = Regex.Replace(message, @"\bx([\-|r|R]|\b)", "ecks$1");
|
||||
message = RegexLowerEndX.Replace(message, "ecks$1");
|
||||
// eckS
|
||||
message = Regex.Replace(message, @"\bX([\-|r|R]|\b)", "ECKS$1");
|
||||
message = RegexUpperEndX.Replace(message, "ECKS$1");
|
||||
|
||||
args.Message = message;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Content.Server.Speech.Components;
|
||||
@@ -8,30 +7,17 @@ namespace Content.Server.Speech.EntitySystems;
|
||||
|
||||
public sealed class MobsterAccentSystem : EntitySystem
|
||||
{
|
||||
private static readonly Regex RegexIng = new(@"(?<=\w\w)(in)g(?!\w)", RegexOptions.IgnoreCase);
|
||||
private static readonly Regex RegexLowerOr = new(@"(?<=\w)o[Rr](?=\w)");
|
||||
private static readonly Regex RegexUpperOr = new(@"(?<=\w)O[Rr](?=\w)");
|
||||
private static readonly Regex RegexLowerAr = new(@"(?<=\w)a[Rr](?=\w)");
|
||||
private static readonly Regex RegexUpperAr = new(@"(?<=\w)A[Rr](?=\w)");
|
||||
private static readonly Regex RegexFirstWord = new(@"^(\S+)");
|
||||
private static readonly Regex RegexLastWord = new(@"(\S+)$");
|
||||
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly ReplacementAccentSystem _replacement = default!;
|
||||
|
||||
private static readonly Dictionary<string, string> DirectReplacements = new()
|
||||
{
|
||||
{ "let me", "lemme" },
|
||||
{ "should", "oughta" },
|
||||
{ "the", "da" },
|
||||
{ "them", "dem" },
|
||||
{ "attack", "whack" },
|
||||
{ "kill", "whack" },
|
||||
{ "murder", "whack" },
|
||||
{ "dead", "sleepin' with da fishies"},
|
||||
{ "hey", "ey'o" },
|
||||
{ "hi", "ey'o"},
|
||||
{ "hello", "ey'o"},
|
||||
{ "rules", "roolz" },
|
||||
{ "you", "yous" },
|
||||
{ "have to", "gotta" },
|
||||
{ "going to", "boutta" },
|
||||
{ "about to", "boutta" },
|
||||
{ "here", "'ere" }
|
||||
};
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -51,20 +37,20 @@ public sealed class MobsterAccentSystem : EntitySystem
|
||||
// thinking -> thinkin'
|
||||
// king -> king
|
||||
//Uses captures groups to make sure the captialization of IN is kept
|
||||
msg = Regex.Replace(msg, @"(?<=\w\w)(in)g(?!\w)", "$1'", RegexOptions.IgnoreCase);
|
||||
msg = RegexIng.Replace(msg, "$1'");
|
||||
|
||||
// or -> uh and ar -> ah in the middle of words (fuhget, tahget)
|
||||
msg = Regex.Replace(msg, @"(?<=\w)o[Rr](?=\w)", "uh");
|
||||
msg = Regex.Replace(msg, @"(?<=\w)O[Rr](?=\w)", "UH");
|
||||
msg = Regex.Replace(msg, @"(?<=\w)a[Rr](?=\w)", "ah");
|
||||
msg = Regex.Replace(msg, @"(?<=\w)A[Rr](?=\w)", "AH");
|
||||
msg = RegexLowerOr.Replace(msg, "uh");
|
||||
msg = RegexUpperOr.Replace(msg, "UH");
|
||||
msg = RegexLowerAr.Replace(msg, "ah");
|
||||
msg = RegexUpperAr.Replace(msg, "AH");
|
||||
|
||||
// Prefix
|
||||
if (_random.Prob(0.15f))
|
||||
{
|
||||
//Checks if the first word of the sentence is all caps
|
||||
//So the prefix can be allcapped and to not resanitize the captial
|
||||
var firstWordAllCaps = !Regex.Match(msg, @"^(\S+)").Value.Any(char.IsLower);
|
||||
var firstWordAllCaps = !RegexFirstWord.Match(msg).Value.Any(char.IsLower);
|
||||
var pick = _random.Next(1, 2);
|
||||
|
||||
// Reverse sanitize capital
|
||||
@@ -84,7 +70,7 @@ public sealed class MobsterAccentSystem : EntitySystem
|
||||
{
|
||||
//Checks if the last word of the sentence is all caps
|
||||
//So the suffix can be allcapped
|
||||
var lastWordAllCaps = !Regex.Match(msg, @"(\S+)$").Value.Any(char.IsLower);
|
||||
var lastWordAllCaps = !RegexLastWord.Match(msg).Value.Any(char.IsLower);
|
||||
var suffix = "";
|
||||
if (component.IsBoss)
|
||||
{
|
||||
@@ -94,7 +80,7 @@ public sealed class MobsterAccentSystem : EntitySystem
|
||||
else
|
||||
{
|
||||
var pick = _random.Next(1, 3);
|
||||
suffix = Loc.GetString($"accent-mobster-suffix-minion-{pick}");
|
||||
suffix = Loc.GetString($"accent-mobster-suffix-minion-{pick}");
|
||||
}
|
||||
if (lastWordAllCaps)
|
||||
suffix = suffix.ToUpper();
|
||||
|
||||
@@ -5,6 +5,9 @@ namespace Content.Server.Speech.EntitySystems;
|
||||
|
||||
public sealed class MothAccentSystem : EntitySystem
|
||||
{
|
||||
private static readonly Regex RegexLowerBuzz = new Regex("z{1,3}");
|
||||
private static readonly Regex RegexUpperBuzz = new Regex("Z{1,3}");
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -16,10 +19,10 @@ public sealed class MothAccentSystem : EntitySystem
|
||||
var message = args.Message;
|
||||
|
||||
// buzzz
|
||||
message = Regex.Replace(message, "z{1,3}", "zzz");
|
||||
message = RegexLowerBuzz.Replace(message, "zzz");
|
||||
// buZZZ
|
||||
message = Regex.Replace(message, "Z{1,3}", "ZZZ");
|
||||
|
||||
message = RegexUpperBuzz.Replace(message, "ZZZ");
|
||||
|
||||
args.Message = message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace Content.Server.Speech.EntitySystems;
|
||||
|
||||
public sealed partial class ParrotAccentSystem : EntitySystem
|
||||
{
|
||||
private static readonly Regex WordCleanupRegex = new Regex("[^A-Za-z0-9 -]");
|
||||
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
public override void Initialize()
|
||||
@@ -27,7 +29,7 @@ public sealed partial class ParrotAccentSystem : EntitySystem
|
||||
if (_random.Prob(entity.Comp.LongestWordRepeatChance))
|
||||
{
|
||||
// Don't count non-alphanumeric characters as parts of words
|
||||
var cleaned = Regex.Replace(message, "[^A-Za-z0-9 -]", string.Empty);
|
||||
var cleaned = WordCleanupRegex.Replace(message, string.Empty);
|
||||
// Split on whitespace and favor words towards the end of the message
|
||||
var words = cleaned.Split(null).Reverse();
|
||||
// Find longest word
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace Content.Server.Speech.EntitySystems;
|
||||
|
||||
public sealed class PirateAccentSystem : EntitySystem
|
||||
{
|
||||
private static readonly Regex FirstWordAllCapsRegex = new(@"^(\S+)");
|
||||
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly ReplacementAccentSystem _replacement = default!;
|
||||
|
||||
@@ -26,7 +28,7 @@ public sealed class PirateAccentSystem : EntitySystem
|
||||
return msg;
|
||||
//Checks if the first word of the sentence is all caps
|
||||
//So the prefix can be allcapped and to not resanitize the captial
|
||||
var firstWordAllCaps = !Regex.Match(msg, @"^(\S+)").Value.Any(char.IsLower);
|
||||
var firstWordAllCaps = !FirstWordAllCapsRegex.Match(msg).Value.Any(char.IsLower);
|
||||
|
||||
var pick = _random.Pick(component.PirateWords);
|
||||
var pirateWord = Loc.GetString(pick);
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace Content.Server.Speech.EntitySystems
|
||||
{
|
||||
public sealed class ScrambledAccentSystem : EntitySystem
|
||||
{
|
||||
private static readonly Regex RegexLoneI = new(@"(?<=\ )i(?=[\ \.\?]|$)");
|
||||
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
public override void Initialize()
|
||||
@@ -34,7 +36,7 @@ namespace Content.Server.Speech.EntitySystems
|
||||
msg = msg[0].ToString().ToUpper() + msg.Remove(0, 1);
|
||||
|
||||
// Capitalize lone i's
|
||||
msg = Regex.Replace(msg, @"(?<=\ )i(?=[\ \.\?]|$)", "I");
|
||||
msg = RegexLoneI.Replace(msg, "I");
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,12 @@ namespace Content.Server.Speech.EntitySystems;
|
||||
|
||||
public sealed class SouthernAccentSystem : EntitySystem
|
||||
{
|
||||
private static readonly Regex RegexIng = new(@"ing\b");
|
||||
private static readonly Regex RegexAnd = new(@"\band\b");
|
||||
private static readonly Regex RegexDve = new("d've");
|
||||
|
||||
[Dependency] private readonly ReplacementAccentSystem _replacement = default!;
|
||||
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -20,9 +24,9 @@ public sealed class SouthernAccentSystem : EntitySystem
|
||||
message = _replacement.ApplyReplacements(message, "southern");
|
||||
|
||||
//They shoulda started runnin' an' hidin' from me!
|
||||
message = Regex.Replace(message, @"ing\b", "in'");
|
||||
message = Regex.Replace(message, @"\band\b", "an'");
|
||||
message = Regex.Replace(message, "d've", "da");
|
||||
message = RegexIng.Replace(message, "in'");
|
||||
message = RegexAnd.Replace(message, "an'");
|
||||
message = RegexDve.Replace(message, "da");
|
||||
args.Message = message;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace Content.Shared.Preferences
|
||||
[Serializable, NetSerializable]
|
||||
public sealed partial class HumanoidCharacterProfile : ICharacterProfile
|
||||
{
|
||||
private static readonly Regex RestrictedNameRegex = new("[^A-Z,a-z,0-9, -]");
|
||||
private static readonly Regex ICNameCaseRegex = new(@"^(?<word>\w)|\b(?<word>\w)(?=\w*$)");
|
||||
|
||||
public const int MaxNameLength = 32;
|
||||
public const int MaxDescLength = 512;
|
||||
|
||||
@@ -418,15 +421,13 @@ namespace Content.Shared.Preferences
|
||||
|
||||
if (configManager.GetCVar(CCVars.RestrictedNames))
|
||||
{
|
||||
name = Regex.Replace(name, @"[^A-Z,a-z,0-9, -]", string.Empty);
|
||||
name = RestrictedNameRegex.Replace(name, string.Empty);
|
||||
}
|
||||
|
||||
if (configManager.GetCVar(CCVars.ICNameCase))
|
||||
{
|
||||
// This regex replaces the first character of the first and last words of the name with their uppercase version
|
||||
name = Regex.Replace(name,
|
||||
@"^(?<word>\w)|\b(?<word>\w)(?=\w*$)",
|
||||
m => m.Groups["word"].Value.ToUpper());
|
||||
name = ICNameCaseRegex.Replace(name, m => m.Groups["word"].Value.ToUpper());
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(name))
|
||||
|
||||
Reference in New Issue
Block a user