// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.IO; using System.Linq; using AutomationTool; using System.Threading; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace Gauntlet { public class Params { public string[] AllArguments { get; protected set; } public Params(IEnumerableInArgs) { // remove any leading - AllArguments = InArgs.Select(S => S.StartsWith("-") ? S.Substring(1) : S).ToArray(); } /// /// Parses the argument list for a parameter and returns whether it is defined or not. /// /// Param to check for. /// True if param was found, false otherwise. public bool ParseParam(string Param) { foreach (string Arg in AllArguments) { string StringArg = Arg; if (StringArg.ToString().Equals(Param, StringComparison.InvariantCultureIgnoreCase)) { return true; } } return false; } /// /// Parses the argument list for a set of parameters and returns whether any are defined or not. /// Useful for cases where you want one setting to have multiple possible command line triggers /// /// /// public bool ParseParams(params string[] Params) { foreach(string Param in Params) { if(ParseParam(Param)) { return true; } } return false; } /// /// Parses multiple values from a param. The multiple values can either be specified as repeated /// arguments, e.g. -foo=one -foo=two, or when 'CommaSeparated' is true as a comma-separated /// list, e.g. -foo=one,two, -foo="one, two". /// /// /// /// public List ParseValues(string Param, bool CommaSeparated=false) { List FoundValues = new List(); if (!Param.EndsWith("=")) { Param += "="; } foreach (string Arg in AllArguments) { string StringArg = Arg; if (StringArg.StartsWith(Param, StringComparison.InvariantCultureIgnoreCase)) { string Value = StringArg.Substring(Param.Length); if (CommaSeparated == false) { FoundValues.Add(Value); } else { // split on comma and trim FoundValues.AddRange(Value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(S => S.Trim())); /* * string[] CSVs = Value.Split(new[] { ',' }); for (int i = 0; i < CSVs.Length; i++) { string Item = CSVs[i]; bool Bracketsmatch = false; do { int BracketCount = Item.Count(c => c == '(') - Item.Count(c => c == ')'); Bracketsmatch = BracketCount == 0; if (!Bracketsmatch) { i++; if (i == CSVs.Length) { char MissingBracket = BracketCount > 0 ? '(' : ')'; throw new AutomationException("Missing {0} in param {1}", MissingBracket, Value); } Item += "," + CSVs[++i]; } } while (!Bracketsmatch); FoundValues.Add(Item); }*/ } } } return FoundValues; } /// /// Parses the argument list for a string parameter and reads its value. /// Ex. ParseParamValue(Args, "map=") /// /// Param to read its value. /// /// Returns the value or Default if the parameter was not found. public string ParseValue(string Param, string Default = null) { var Values = ParseValues(Param); return Values.Count > 0 ? Values.First() : Default; } /// /// Parses the argument list for an int parameter and reads its value. /// Ex. ParseParamValue(Args, "timeout=") /// /// Param to read its value. /// /// Returns the value or Default if the parameter was not found. public int ParseValue(string Param, int Default = 0) { string Value = ParseValue(Param, Convert.ToString(Default)); if (Value == null) { return Default; } return Convert.ToInt32(Value); } /// /// Parses the argument list for a float parameter and reads its value. /// Ex. ParseParamValue(Args, "timeout=") /// /// Param to read its value. /// /// Returns the value or Default if the parameter was not found. public float ParseValue(string Param, float Default = 0) { string Value = ParseValue(Param, Convert.ToString(Default)); if (Value == null) { return Default; } return Convert.ToSingle(Value); } } public class ArgumentWithParams : Params { public string Argument { get; protected set; } public ArgumentWithParams(string InArgument, IEnumerable InArgs) : base(InArgs) { Argument = InArgument; } // Turns a string like Test1,Test2(foo,bar=3) into a list of tuples where item1 // is the name of the string and item2 a Params object public static List CreateFromString(string Input) { List TestsWithParams = new List(); // turn Name(p1,etc) into a collection of Name|(p1,etc) groups MatchCollection Matches = Regex.Matches(Input, @"([^,]+?)(?:\((.+?)\))?(?:,|\z)"); foreach (Match M in Matches) { string Name = M.Groups[1].ToString().Trim(); string Params = M.Groups[2].ToString(); // to avoid an insane regex parse the params manually so we can deal with comma's in quotes List TestArgs = new List(); string CurrentArg = ""; // global state while parsing bool InQuote = false; for (int i = 0; i < Params.Length; i++) { char C = Params[i]; bool LastChar = i == Params.Length - 1; bool IsQuote = C == '\''; // only treat comma's and brackets as special outside of quotes bool IsComma = C == ',' && !InQuote; // if starting or ending quotes, just flip our state and continue if (IsQuote) { InQuote = !InQuote; continue; } // if this is a comma, wrap up the current arg if (IsComma) { TestArgs.Add(CurrentArg.Trim()); CurrentArg = ""; } else { CurrentArg += C; } } // add last arg if (CurrentArg.Length > 0) { TestArgs.Add(CurrentArg.Trim()); } TestsWithParams.Add(new ArgumentWithParams(Name, TestArgs.ToArray())); } return TestsWithParams; } } }