using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
////REVIEW: why is this public?
////TODO: add array support
////TODO: switch parsing to use to Substring
namespace UnityEngine.InputSystem.Utilities
{
///
/// A combination of a name and an optional list of named parameter values. For example, "Clamp(min=1,max=2)".
///
public struct NameAndParameters
{
public string name { get; set; }
public ReadOnlyArray parameters { get; set; }
public override string ToString()
{
if (parameters.Count == 0)
return name;
var parameterString = string.Join(NamedValue.Separator, parameters.Select(x => x.ToString()).ToArray());
return $"{name}({parameterString})";
}
public static IEnumerable ParseMultiple(string text)
{
List list = null;
if (!ParseMultiple(text, ref list))
return Enumerable.Empty();
return list;
}
internal static bool ParseMultiple(string text, ref List list)
{
text = text.Trim();
if (string.IsNullOrEmpty(text))
return false;
if (list == null)
list = new List();
else
list.Clear();
var index = 0;
var textLength = text.Length;
while (index < textLength)
list.Add(ParseNameAndParameters(text, ref index));
return true;
}
internal static string ParseName(string text)
{
if (text == null)
throw new ArgumentNullException(nameof(text));
var index = 0;
return ParseNameAndParameters(text, ref index, true).name;
}
public static NameAndParameters Parse(string text)
{
if (text == null)
throw new ArgumentNullException(nameof(text));
var index = 0;
return ParseNameAndParameters(text, ref index);
}
private static NameAndParameters ParseNameAndParameters(string text, ref int index, bool nameOnly = false)
{
var textLength = text.Length;
// Skip whitespace.
while (index < textLength && char.IsWhiteSpace(text[index]))
++index;
// Parse name.
var nameStart = index;
while (index < textLength)
{
var nextChar = text[index];
if (nextChar == '(' || nextChar == NamedValue.Separator[0] || char.IsWhiteSpace(nextChar))
break;
++index;
}
if (index - nameStart == 0)
throw new ArgumentException($"Expecting name at position {nameStart} in '{text}'", nameof(text));
var name = text.Substring(nameStart, index - nameStart);
if (nameOnly)
return new NameAndParameters {name = name};
// Skip whitespace.
while (index < textLength && char.IsWhiteSpace(text[index]))
++index;
// Parse parameters.
NamedValue[] parameters = null;
if (index < textLength && text[index] == '(')
{
++index;
var closeParenIndex = text.IndexOf(')', index);
if (closeParenIndex == -1)
throw new ArgumentException($"Expecting ')' after '(' at position {index} in '{text}'", nameof(text));
var parameterString = text.Substring(index, closeParenIndex - index);
parameters = NamedValue.ParseMultiple(parameterString);
index = closeParenIndex + 1;
}
if (index < textLength && (text[index] == ',' || text[index] == InputBinding.Separator))
++index;
return new NameAndParameters {name = name, parameters = new ReadOnlyArray(parameters)};
}
}
}