2019-08-03 12:50:41 +02:00
using System ;
using System.Collections.Generic ;
using System.Collections ;
2019-08-26 13:11:56 +02:00
using System.Reflection ;
using ln.logging ;
using System.ComponentModel ;
2019-08-03 12:50:41 +02:00
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 ;
}
}
2019-08-26 13:11:56 +02:00
/// <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>
2019-08-03 12:50:41 +02:00
public class ArgumentContainer
{
List < Argument > arguments ;
List < String > additionalArguments ;
2019-08-26 13:11:56 +02:00
public string [ ] AdditionalArguments = > additionalArguments . ToArray ( ) ;
2019-08-03 12:50:41 +02:00
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 )
{
2020-02-04 09:00:22 +01:00
if ( longName ! = null )
2019-08-03 12:50:41 +02:00
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 ) ;
2019-08-26 13:11:56 +02:00
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 ( ) ;
}
2019-08-03 12:50:41 +02:00
}
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 ) ;
}
}
}
2019-08-26 13:11:56 +02:00
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 ) ;
}
2019-08-03 12:50:41 +02:00
}
}