diff --git a/src/Discord.Net/Format.cs b/src/Discord.Net/Format.cs
index 6c62ba4aa..2218a4767 100644
--- a/src/Discord.Net/Format.cs
+++ b/src/Discord.Net/Format.cs
@@ -1,23 +1,91 @@
-using System.Text;
+using Discord.Net.API;
+using System.Text;
using System.Text.RegularExpressions;
namespace Discord
{
- public static class Format
+ public static class Format
{
- private static readonly Regex _escapeRegex;
- private static readonly MatchEvaluator _escapeEvaluator;
+ private static readonly string[] _patterns;
+ private static readonly StringBuilder _builder;
static Format()
{
- const string innerPattern = "[_*]|~~";
- _escapeRegex = new Regex($@"(?<=^|\W)(?:{innerPattern})|(?:{innerPattern})(?=\W|$)|\\", RegexOptions.Compiled);
- _escapeEvaluator = new MatchEvaluator(e => '\\' + e.Value);
- }
+ _patterns = new string[] { "__", "_", "**", "*", "~~" };
+ _builder = new StringBuilder(DiscordAPIClient.MaxMessageSize);
+ }
/// Removes all special formatting characters from the provided text.
private static string Escape(string text)
- => _escapeRegex.Replace(text, _escapeEvaluator);
+ {
+ lock (_builder)
+ {
+ _builder.Clear();
+
+ //Escape all backslashes
+ for (int i = 0; i < text.Length; i++)
+ {
+ _builder.Append(text[i]);
+ if (text[i] == '\\')
+ _builder.Append('\\');
+ }
+
+ EscapeSubstring(0, _builder.Length);
+
+ return _builder.ToString();
+ }
+ }
+ private static int EscapeSubstring(int start, int end)
+ {
+ int totalAddedChars = 0;
+ for (int i = start; i < end + totalAddedChars; i++)
+ {
+ for (int p = 0; p < _patterns.Length; p++)
+ {
+ string pattern = _patterns[p];
+ if (i + pattern.Length * 2 > _builder.Length)
+ continue;
+ int s = FindPattern(pattern, i, i + 1);
+ if (s == -1) continue;
+ int e = FindPattern(pattern, i + 1, end + totalAddedChars);
+ if (e == -1) continue;
+
+ if (e - s - pattern.Length > 0)
+ {
+ //By going right to left, we dont need to adjust any offsets
+ for (int k = pattern.Length - 1; k >= 0; k--)
+ _builder.Insert(e + k, '\\');
+ for (int k = pattern.Length - 1; k >= 0; k--)
+ _builder.Insert(s + k, '\\');
+ int addedChars = pattern.Length * 2;
+ addedChars += EscapeSubstring(s + pattern.Length * 2, e + pattern.Length);
+ i = e + addedChars + pattern.Length - 1;
+ totalAddedChars += addedChars;
+ break;
+ }
+ }
+ }
+ return totalAddedChars;
+ }
+ private static int FindPattern(string pattern, int start, int end)
+ {
+ for (int j = start; j < end; j++)
+ {
+ if (_builder[j] == '\\')
+ {
+ j++;
+ continue;
+ }
+ for (int k = 0; k < pattern.Length; k++)
+ {
+ if (_builder[j + k] != pattern[k])
+ goto nextpos;
+ }
+ return j;
+ nextpos:;
+ }
+ return -1;
+ }
/// Returns a markdown-formatted string with no formatting, optionally escaping the contents.
public static string Normal(string text, bool escape = true)