208 lines
7.2 KiB
C#
208 lines
7.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections;
|
|
using System.Reflection;
|
|
using ln.logging;
|
|
using System.ComponentModel;
|
|
namespace ln.types
|
|
{
|
|
|
|
public class Argument
|
|
{
|
|
public char Short { get; }
|
|
public String Long { get; }
|
|
|
|
public bool NeedsValue { get; }
|
|
public bool HasValue => Value != null;
|
|
|
|
public String Value { get; set; }
|
|
public int IntegerValue => int.Parse(Value);
|
|
public double DoubleValue => double.Parse(Value);
|
|
|
|
public bool IsSet { get; set; }
|
|
|
|
public Argument(char shortName, string longName)
|
|
{
|
|
Short = shortName;
|
|
Long = longName;
|
|
|
|
NeedsValue = false;
|
|
}
|
|
public Argument(char shortName, string longName, int defaultValue)
|
|
: this(shortName, longName, defaultValue.ToString()) { }
|
|
public Argument(char shortName, string longName, double defaultValue)
|
|
: this(shortName, longName, defaultValue.ToString()) { }
|
|
|
|
public Argument(char shortName, string longName, string defaultValue)
|
|
{
|
|
Short = shortName;
|
|
Long = longName;
|
|
|
|
NeedsValue = true;
|
|
Value = defaultValue;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Argument container.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This class parses command line arguments to a list of predefined well known arguments.
|
|
/// Remaining arguments will be found in <c>AdditionalArguments</c>.
|
|
///
|
|
/// <c>ArgumentContainer</c> also provides a global command line option:
|
|
/// --change-static <para>typename</para> <para>fieldname</para> <para>value</para>
|
|
/// It may be used multiple times on the command line.
|
|
/// It will load the type referenced by the qualified name <para>typename</para> and try to set the static field <para>fieldname</para> to <para>value</para>.
|
|
/// <para>value</para> will be casted to field type via Convert.ChangeType(...)
|
|
/// </remarks>
|
|
public class ArgumentContainer
|
|
{
|
|
List<Argument> arguments;
|
|
List<String> additionalArguments;
|
|
|
|
public string[] AdditionalArguments => additionalArguments.ToArray();
|
|
|
|
public ArgumentContainer()
|
|
{
|
|
arguments = new List<Argument>();
|
|
additionalArguments = new List<string>();
|
|
}
|
|
public ArgumentContainer(IEnumerable<Argument> argumentDefinitions)
|
|
: this()
|
|
{
|
|
arguments.AddRange(argumentDefinitions);
|
|
}
|
|
|
|
public Argument this[string longName]
|
|
{
|
|
get
|
|
{
|
|
if (longName == null)
|
|
throw new ArgumentNullException(nameof(longName));
|
|
|
|
foreach (Argument argument in arguments)
|
|
{
|
|
if (longName.Equals(argument.Long))
|
|
return argument;
|
|
}
|
|
throw new KeyNotFoundException();
|
|
}
|
|
}
|
|
public Argument this[char shortName]
|
|
{
|
|
get
|
|
{
|
|
if (shortName == 0)
|
|
throw new ArgumentNullException(nameof(shortName));
|
|
|
|
foreach (Argument argument in arguments)
|
|
{
|
|
if (shortName.Equals(argument.Short))
|
|
return argument;
|
|
}
|
|
throw new KeyNotFoundException();
|
|
}
|
|
}
|
|
|
|
public bool Contains(string longName)
|
|
{
|
|
if (longName != null)
|
|
foreach (Argument argument in arguments)
|
|
{
|
|
if (longName.Equals(argument.Long))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
public bool Contains(char shortName)
|
|
{
|
|
if (shortName == (char)0)
|
|
return false;
|
|
|
|
foreach (Argument argument in arguments)
|
|
{
|
|
if (shortName.Equals(argument.Short))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public ArgumentContainer Add(Argument argument)
|
|
{
|
|
if (Contains(argument.Short) || Contains(argument.Long))
|
|
throw new ArgumentException(nameof(argument),String.Format("0x{0:x} / {1}",(int)argument.Short,argument.Long));
|
|
|
|
arguments.Add(argument);
|
|
return this;
|
|
}
|
|
public ArgumentContainer Add(char shortName) => Add(new Argument(shortName, null));
|
|
public ArgumentContainer Add(string longName) => Add(new Argument((char)0, longName));
|
|
public ArgumentContainer Add(char shortName, string longName) => Add(new Argument(shortName, longName));
|
|
public ArgumentContainer Add(char shortName, string longName, string defaultValue) => Add(new Argument(shortName, longName, defaultValue));
|
|
public ArgumentContainer Add(int shortName, string longName, string defaultValue) => Add(new Argument((char)shortName, longName, defaultValue));
|
|
|
|
public void Parse(IEnumerable<string> args)
|
|
{
|
|
Queue<string> q = new Queue<string>(args);
|
|
while (q.Count > 0)
|
|
{
|
|
string currentOption = q.Dequeue();
|
|
|
|
if (currentOption[0].Equals('-'))
|
|
{
|
|
if (currentOption[1].Equals('-'))
|
|
{
|
|
String aname = currentOption.Substring(2);
|
|
|
|
if (aname.Equals("change-static"))
|
|
{
|
|
string typeName = q.Dequeue();
|
|
string fieldName = q.Dequeue();
|
|
string value = q.Dequeue();
|
|
ChangeStatic(typeName, fieldName, value);
|
|
}
|
|
else
|
|
{
|
|
Argument argument = this[aname];
|
|
argument.IsSet = true;
|
|
if (argument.NeedsValue)
|
|
argument.Value = q.Dequeue();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (char option in currentOption.Substring(1))
|
|
{
|
|
Argument argument = this[option];
|
|
argument.IsSet = true;
|
|
if (argument.NeedsValue)
|
|
argument.Value = q.Dequeue();
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
additionalArguments.Add(currentOption);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void ChangeStatic(string typeName,string fieldname,string value)
|
|
{
|
|
Type type = Type.GetType(typeName);
|
|
Logging.Log(LogLevel.INFO, "ArgumentContainer: ChangeStatic: Type: {0}",type);
|
|
|
|
FieldInfo fieldInfo = type.GetField(fieldname, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
|
Logging.Log(LogLevel.INFO, "ArgumentContainer: ChangeStatic: Field: {0} {1}", fieldname, fieldInfo);
|
|
|
|
object castValue = Convert.ChangeType(value, fieldInfo.FieldType);
|
|
fieldInfo.SetValue(null,castValue);
|
|
}
|
|
}
|
|
}
|