149 lines
3.9 KiB
C#
149 lines
3.9 KiB
C#
|
using System;
|
||
|
|
||
|
namespace UnityEngine.InputSystem.Utilities
|
||
|
{
|
||
|
// this parser uses Span<T> so it's only available from later unity versions
|
||
|
#if UNITY_2021_2_OR_NEWER
|
||
|
internal struct PredictiveParser
|
||
|
{
|
||
|
public void ExpectSingleChar(ReadOnlySpan<char> str, char c)
|
||
|
{
|
||
|
if (str[m_Position] != c)
|
||
|
throw new InvalidOperationException($"Expected a '{c}' character at position {m_Position} in : {str.ToString()}");
|
||
|
|
||
|
++m_Position;
|
||
|
}
|
||
|
|
||
|
public int ExpectInt(ReadOnlySpan<char> str)
|
||
|
{
|
||
|
int pos = m_Position;
|
||
|
|
||
|
int sign = 1;
|
||
|
if (str[pos] == '-')
|
||
|
{
|
||
|
sign = -1;
|
||
|
++pos;
|
||
|
}
|
||
|
|
||
|
int value = 0;
|
||
|
for (;;)
|
||
|
{
|
||
|
var n = str[pos];
|
||
|
if (n >= '0' && n <= '9')
|
||
|
{
|
||
|
value *= 10;
|
||
|
value += n - '0';
|
||
|
++pos;
|
||
|
}
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (m_Position == pos)
|
||
|
throw new InvalidOperationException($"Expected an int at position {m_Position} in {str.ToString()}");
|
||
|
|
||
|
m_Position = pos;
|
||
|
return value * sign;
|
||
|
}
|
||
|
|
||
|
public ReadOnlySpan<char> ExpectString(ReadOnlySpan<char> str)
|
||
|
{
|
||
|
var startPos = m_Position;
|
||
|
if (str[startPos] != '\"')
|
||
|
throw new InvalidOperationException($"Expected a '\"' character at position {m_Position} in {str.ToString()}");
|
||
|
|
||
|
++m_Position;
|
||
|
|
||
|
for (;;)
|
||
|
{
|
||
|
var c = str[m_Position];
|
||
|
c |= ' ';
|
||
|
if (c >= 'a' && c <= 'z')
|
||
|
{
|
||
|
++m_Position;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// if the first non-alpha character is not a quote, throw
|
||
|
if (str[m_Position] != '\"')
|
||
|
throw new InvalidOperationException($"Expected a closing '\"' character at position {m_Position} in string: {str.ToString()}");
|
||
|
|
||
|
if (m_Position - startPos == 1)
|
||
|
return ReadOnlySpan<char>.Empty;
|
||
|
|
||
|
var output = str.Slice(startPos + 1, m_Position - startPos - 1);
|
||
|
|
||
|
++m_Position;
|
||
|
return output;
|
||
|
}
|
||
|
|
||
|
public bool AcceptSingleChar(ReadOnlySpan<char> str, char c)
|
||
|
{
|
||
|
if (str[m_Position] != c)
|
||
|
return false;
|
||
|
|
||
|
m_Position++;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public bool AcceptString(ReadOnlySpan<char> input, out ReadOnlySpan<char> output)
|
||
|
{
|
||
|
output = default;
|
||
|
var startPos = m_Position;
|
||
|
var endPos = startPos;
|
||
|
if (input[endPos] != '\"')
|
||
|
return false;
|
||
|
|
||
|
++endPos;
|
||
|
|
||
|
for (;;)
|
||
|
{
|
||
|
var c = input[endPos];
|
||
|
c |= ' ';
|
||
|
if (c >= 'a' && c <= 'z')
|
||
|
{
|
||
|
++endPos;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// if the first non-alpha character is not a quote, throw
|
||
|
if (input[endPos] != '\"')
|
||
|
return false;
|
||
|
|
||
|
// empty string?
|
||
|
if (m_Position - startPos == 1)
|
||
|
output = ReadOnlySpan<char>.Empty;
|
||
|
else
|
||
|
output = input.Slice(startPos + 1, endPos - startPos - 1);
|
||
|
|
||
|
m_Position = endPos + 1;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public void AcceptInt(ReadOnlySpan<char> str)
|
||
|
{
|
||
|
// skip negative sign
|
||
|
if (str[m_Position] == '-')
|
||
|
++m_Position;
|
||
|
|
||
|
for (;;)
|
||
|
{
|
||
|
var n = str[m_Position];
|
||
|
if (n >= '0' && n <= '9')
|
||
|
++m_Position;
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private int m_Position;
|
||
|
}
|
||
|
#endif
|
||
|
}
|