Code runs in LinqPad.
Code runs in LinqPad.
This should be significantly faster than your original code because it speeds up the conditionals by using pattern matching instead of overloadable operators. Also, the local functions can be in-lined, meaning they will be executed in place, which is even more efficient than the `Goto` statements. And now it's not pure spaghetti.
string json = """
{
"test": 0,
"data": "value"
}
""";
JsonStringRunner runner = new();
List<FAMatch> matches = new();
FAMatch current = default;
Stopwatch sw = new();
sw.Start();
do{
current = runner.GetMatch(json);
matches.Add(current);
} while(!runner.isDone);
sw.Stop();
matches.Dump();
sw.Dump();
internal record struct FAMatch(int token, string match, int position, int length, int column)
{
internal static FAMatch Create(int token, string match, int position, int length, int column)
=> new(token, match, position, length, column);
}
internal abstract class FAStringRunner
{
protected int position = -1, line = 0, column = 0;
internal bool isDone = false;
}
internal sealed partial class JsonStringRunner : FAStringRunner
{
private void Advance(string s, ref int ch, ref int len, bool flag)
{
ch = s[position];
position++;
len++;
isDone = !(position < s.Length);
}
private FAMatch NextMatchImpl(string s)
{
int ch;
int len;
int l;
int c;
ch = -1;
len = 0;
if ((this.position is -1))
{
this.position = 0;
}
int p = this.position;
l = this.line;
c = this.column;
this.Advance(s, ref ch, ref len, true);
switch (ch)
{
case 9 or 10 or 13 or 32:
if(ch is 10 or 13){
l = line++;
}
return q1();
case 34:
return q2();
case 44:
return q9();
case 45:
return q10();
case 48:
return q11();
case >= 49 and <= 57:
return q17();
case 58:
return q18();
case 91:
return q19();
case 93:
return q20();
case 102:
return q21();
case 110:
return q26();
case 116:
return q30();
case 123:
return q32();
case 125:
return q33();
}
return errorout();
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q1()
{
while (ch is 9 or 10 or 13 or 32)
{
this.Advance(s, ref ch, ref len, false);
}
return FAMatch.Create(10, s.Substring(p, len), p, l, c);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q2()
{
while (ch is (((((>= 0)
and (<= 9))
or ((>= 11)
and (<= 33)))
or ((>= 35)
and (<= 91)))
or ((>= 93)
and (<= 1114111))))
{
this.Advance(s, ref ch, ref len, false);
}
if ((ch is 34))
{
this.Advance(s, ref ch, ref len, false);
return q3();
}
if ((ch is 92))
{
this.Advance(s, ref ch, ref len, false);
return q4();
}
return default;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q3() => FAMatch.Create(9, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q4()
{
if (ch is 34 or 47
or 92
or 98
or 102
or 110
or 114
or 116)
{
this.Advance(s, ref ch, ref len, false);
return q2();
}
if (ch is 117)
{
this.Advance(s, ref ch, ref len, false);
return q5();
}
return errorout();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q5()
{
if (ch is (>= 48 and <= 57) or (>= 65 and <= 70)
or (>= 97 and <= 102))
{
this.Advance(s, ref ch, ref len, false);
return q6();
}
return errorout();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q6()
{
if (ch is (>= 48 and <= 57) or (>= 65 and <= 70)
or (>= 97 and <= 102))
{
this.Advance(s, ref ch, ref len, false);
return q7();
}
return errorout();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q7() => FAMatch.Create(7, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q9() => FAMatch.Create(9, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q10() => FAMatch.Create(10, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q11() => FAMatch.Create(11, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q17() => FAMatch.Create(17, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q18() => FAMatch.Create(18, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q19() => FAMatch.Create(19, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q20() => FAMatch.Create(20, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q21() => FAMatch.Create(21, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q26() => FAMatch.Create(26, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q30() => FAMatch.Create(110, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q32() => FAMatch.Create(123, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch q33() => FAMatch.Create(125, s.Substring(p, len), p, l, c);
[MethodImpl(MethodImplOptions.AggressiveInlining)] FAMatch errorout() => FAMatch.Create(0, s.Substring(p, len), p, l, c);
}
public FAMatch GetMatch(string s) => NextMatchImpl(s);
}
|