OptionDetails.cs
上传用户:huiyue
上传日期:2022-04-08
资源大小:1429k
文件大小:13k
- //
- // OptionDetails.cs
- //
- // Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)
- //
- // (C) 2002 Rafael Teixeira
- //
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- using System;
- using System.Collections;
- using System.IO;
- using System.Reflection;
- namespace Mono.GetOptions
- {
- public enum WhatToDoNext
- {
- AbandonProgram,
- GoAhead
- }
-
- internal enum OptionProcessingResult
- {
- NotThisOption,
- OptionAlone,
- OptionConsumedParameter
- }
- internal class OptionDetails : IComparable
- {
- public string ShortForm;
- public string LongForm;
- public string AlternateForm;
- public string ShortDescription;
- public bool NeedsParameter;
- public int MaxOccurs; // negative means there is no limit
- public int Occurs;
- public bool BooleanOption;
- public Options OptionBundle;
- public MemberInfo MemberInfo;
- public ArrayList Values;
- public System.Type ParameterType;
- public string paramName = null;
- public bool VBCStyleBoolean;
- public bool SecondLevelHelp;
- public bool Hidden;
-
- public OptionDetails NextAlternate = null;
- private string ExtractParamName(string shortDescription)
- {
- int whereBegins = shortDescription.IndexOf("{");
- if (whereBegins < 0)
- paramName = "PARAM";
- else {
- int whereEnds = shortDescription.IndexOf("}");
- if (whereEnds < whereBegins)
- whereEnds = shortDescription.Length+1;
-
- paramName = shortDescription.Substring(whereBegins + 1, whereEnds - whereBegins - 1);
- shortDescription =
- shortDescription.Substring(0, whereBegins) +
- paramName +
- shortDescription.Substring(whereEnds + 1);
- }
- return shortDescription;
- }
- public string ParamName { get { return paramName; } }
-
- private bool verboseParsing { get { return OptionBundle.VerboseParsingOfOptions || OptionBundle.DebuggingOfOptions; } }
- // private bool debugOptions { get { return OptionBundle.DebuggingOfOptions; } }
- private OptionsParsingMode parsingMode { get { return OptionBundle.ParsingMode; } }
-
- private bool useGNUFormat { get { return (parsingMode & OptionsParsingMode.GNU_DoubleDash) == OptionsParsingMode.GNU_DoubleDash; } }
-
- private bool dontSplitOnCommas { get { return OptionBundle.DontSplitOnCommas; } }
- private string linuxLongPrefix {
- get {
- return (useGNUFormat? "--":"-");
- }
- }
-
- public string DefaultForm
- {
- get {
- string shortPrefix = "-";
- string longPrefix = linuxLongPrefix;
- if (parsingMode == OptionsParsingMode.Windows) {
- shortPrefix = "/";
- longPrefix = "/";
- }
- if (this.ShortForm != string.Empty)
- return shortPrefix+this.ShortForm;
- else
- return longPrefix+this.LongForm;
- }
- }
- private string optionHelp = null;
-
- public override string ToString()
- {
- if (optionHelp == null)
- {
- string shortPrefix;
- string longPrefix;
- bool hasLongForm = (this.LongForm != null && this.LongForm != string.Empty);
- if (this.OptionBundle.ParsingMode == OptionsParsingMode.Windows) {
- shortPrefix = "/";
- longPrefix = "/";
- } else {
- shortPrefix = "-";
- longPrefix = linuxLongPrefix;
- }
- optionHelp = " ";
- optionHelp += (this.ShortForm != string.Empty) ? shortPrefix+this.ShortForm+" " : " ";
- optionHelp += hasLongForm ? longPrefix+this.LongForm : "";
- if (NeedsParameter) {
- if (hasLongForm)
- optionHelp += ":";
- optionHelp += ParamName;
- } else if (BooleanOption && VBCStyleBoolean) {
- optionHelp += "[+|-]";
- }
- optionHelp += "t";
- if (this.AlternateForm != string.Empty && this.AlternateForm != null)
- optionHelp += "Also "+ shortPrefix + this.AlternateForm + (NeedsParameter?(":"+ParamName):"") +". ";
- optionHelp += this.ShortDescription;
- }
- return optionHelp;
- }
- private static System.Type TypeOfMember(MemberInfo memberInfo)
- {
- if ((memberInfo.MemberType == MemberTypes.Field && memberInfo is FieldInfo))
- return ((FieldInfo)memberInfo).FieldType;
- if ((memberInfo.MemberType == MemberTypes.Property && memberInfo is PropertyInfo))
- return ((PropertyInfo)memberInfo).PropertyType;
- if ((memberInfo.MemberType == MemberTypes.Method && memberInfo is MethodInfo))
- {
- if (((MethodInfo)memberInfo).ReturnType.FullName != typeof(WhatToDoNext).FullName)
- throw new NotSupportedException("Option method must return '" + typeof(WhatToDoNext).FullName + "'");
- ParameterInfo[] parameters = ((MethodInfo)memberInfo).GetParameters();
- if ((parameters == null) || (parameters.Length == 0))
- return null;
- else
- return parameters[0].ParameterType;
- }
- throw new NotSupportedException("'" + memberInfo.MemberType + "' memberType is not supported");
- }
- public OptionDetails(MemberInfo memberInfo, OptionAttribute option, Options optionBundle)
- {
- this.ShortForm = ("" + option.ShortForm).Trim();
- if (option.LongForm == null)
- this.LongForm = string.Empty;
- else
- this.LongForm = (option.LongForm == string.Empty)? memberInfo.Name:option.LongForm;
- this.AlternateForm = option.AlternateForm;
- this.ShortDescription = ExtractParamName(option.ShortDescription);
- this.Occurs = 0;
- this.OptionBundle = optionBundle;
- this.BooleanOption = false;
- this.MemberInfo = memberInfo;
- this.NeedsParameter = false;
- this.Values = null;
- this.MaxOccurs = 1;
- this.VBCStyleBoolean = option.VBCStyleBoolean;
- this.SecondLevelHelp = option.SecondLevelHelp;
- this.Hidden = false; // TODO: check other attributes
-
- this.ParameterType = TypeOfMember(memberInfo);
- if (this.ParameterType != null)
- {
- if (this.ParameterType.FullName != "System.Boolean")
- {
- if (this.LongForm.IndexOf(':') >= 0)
- throw new InvalidOperationException("Options with an embedded colon (':') in their visible name must be boolean!!! [" +
- this.MemberInfo.ToString() + " isn't]");
-
- this.NeedsParameter = true;
- if (option.MaxOccurs != 1)
- {
- if (this.ParameterType.IsArray)
- {
- this.Values = new ArrayList();
- this.MaxOccurs = option.MaxOccurs;
- }
- else
- {
- if (this.MemberInfo is MethodInfo || this.MemberInfo is PropertyInfo)
- this.MaxOccurs = option.MaxOccurs;
- else
- throw new InvalidOperationException("MaxOccurs set to non default value (" + option.MaxOccurs + ") for a [" +
- this.MemberInfo.ToString() + "] option");
- }
- }
- }
- else
- {
- this.BooleanOption = true;
- if (option.MaxOccurs != 1)
- {
- if (this.MemberInfo is MethodInfo || this.MemberInfo is PropertyInfo)
- this.MaxOccurs = option.MaxOccurs;
- else
- throw new InvalidOperationException("MaxOccurs set to non default value (" + option.MaxOccurs + ") for a [" +
- this.MemberInfo.ToString() + "] option");
- }
- }
- }
- }
- internal string Key
- {
- get {
- if (useGNUFormat) {
- string ShortID = this.ShortForm.ToUpper();
- if (ShortID == string.Empty)
- ShortID = "ZZ";
- return ShortID + " " + this.LongForm;
- } else
- return this.LongForm + " " + this.ShortForm;
- }
- }
- int IComparable.CompareTo(object other)
- {
- return Key.CompareTo(((OptionDetails)other).Key);
- }
- public void TransferValues()
- {
- if (Values != null)
- {
- if (MemberInfo is FieldInfo)
- {
- ((FieldInfo)MemberInfo).SetValue(OptionBundle, Values.ToArray(ParameterType.GetElementType()));
- return;
- }
- if (MemberInfo is PropertyInfo)
- {
- ((PropertyInfo)MemberInfo).SetValue(OptionBundle, Values.ToArray(ParameterType.GetElementType()), null);
- return;
- }
- if ((WhatToDoNext)((MethodInfo)MemberInfo).Invoke(OptionBundle, new object[] { Values.ToArray(ParameterType.GetElementType()) }) == WhatToDoNext.AbandonProgram)
- System.Environment.Exit(1);
- }
- }
- private int HowManyBeforeExceedingMaxOccurs(int howMany)
- {
- if (MaxOccurs > 0 && (Occurs + howMany) > MaxOccurs) {
- System.Console.Error.WriteLine("Option " + LongForm + " can be used at most " + MaxOccurs + " times. Ignoring extras...");
- howMany = MaxOccurs - Occurs;
- }
- Occurs += howMany;
- return howMany;
- }
-
- private bool AddingOneMoreExceedsMaxOccurs { get { return HowManyBeforeExceedingMaxOccurs(1) < 1; } }
- private void DoIt(bool setValue)
- {
- if (AddingOneMoreExceedsMaxOccurs)
- return;
- if (verboseParsing)
- Console.WriteLine("<{0}> set to [{1}]", this.LongForm, setValue);
- if (MemberInfo is FieldInfo)
- {
- ((FieldInfo)MemberInfo).SetValue(OptionBundle, setValue);
- return;
- }
- if (MemberInfo is PropertyInfo)
- {
- ((PropertyInfo)MemberInfo).SetValue(OptionBundle, setValue, null);
- return;
- }
- if ((WhatToDoNext)((MethodInfo)MemberInfo).Invoke(OptionBundle, null) == WhatToDoNext.AbandonProgram)
- System.Environment.Exit(1);
- }
-
- private void DoIt(string parameterValue)
- {
- if (parameterValue == null)
- parameterValue = "";
- string[] parameterValues;
-
- if (dontSplitOnCommas || MaxOccurs == 1)
- parameterValues = new string[] { parameterValue };
- else
- parameterValues = parameterValue.Split(',');
- int waitingToBeProcessed = HowManyBeforeExceedingMaxOccurs(parameterValues.Length);
- foreach (string parameter in parameterValues)
- {
- if (waitingToBeProcessed-- <= 0)
- break;
-
- object convertedParameter = null;
- if (verboseParsing)
- Console.WriteLine("<" + this.LongForm + "> set to [" + parameter + "]");
- if (Values != null && parameter != null) {
- try {
- convertedParameter = Convert.ChangeType(parameter, ParameterType.GetElementType());
- } catch (Exception ex) {
- Console.WriteLine(String.Format("The value '{0}' is not convertible to the appropriate type '{1}' for the {2} option", parameter, ParameterType.GetElementType().Name, DefaultForm));
- }
- Values.Add(convertedParameter);
- continue;
- }
- if (parameter != null) {
- try {
- convertedParameter = Convert.ChangeType(parameter, ParameterType);
- } catch (Exception ex) {
- Console.WriteLine(String.Format("The value '{0}' is not convertible to the appropriate type '{1}' for the {2} option", parameter, ParameterType.Name, DefaultForm));
- continue;
- }
- }
- if (MemberInfo is FieldInfo) {
- ((FieldInfo)MemberInfo).SetValue(OptionBundle, convertedParameter);
- continue;
- }
- if (MemberInfo is PropertyInfo) {
- ((PropertyInfo)MemberInfo).SetValue(OptionBundle, convertedParameter, null);
- continue;
- }
- if ((WhatToDoNext)((MethodInfo)MemberInfo).Invoke(OptionBundle, new object[] { convertedParameter }) == WhatToDoNext.AbandonProgram)
- System.Environment.Exit(1);
- }
- }
- private bool IsThisOption(string arg)
- {
- if (arg != null && arg != string.Empty)
- {
- arg = arg.TrimStart('-', '/');
- if (VBCStyleBoolean)
- arg = arg.TrimEnd('-', '+');
- return (arg == ShortForm || arg == LongForm || arg == AlternateForm);
- }
- return false;
- }
- public static void LinkAlternatesInsideList(ArrayList list)
- {
- Hashtable baseForms = new Hashtable(list.Count);
- foreach (OptionDetails option in list) {
- if (option.LongForm != null && option.LongForm.Trim().Length > 0) {
- string[] parts = option.LongForm.Split(':');
- if (parts.Length < 2) {
- baseForms.Add(option.LongForm, option);
- } else {
- OptionDetails baseForm = (OptionDetails)baseForms[parts[0]];
- if (baseForm != null) {
- // simple linked list
- option.NextAlternate = baseForm.NextAlternate;
- baseForm.NextAlternate = option;
- }
- }
- }
- }
- }
- private bool IsAlternate(string compoundArg)
- {
- OptionDetails next = NextAlternate;
- while (next != null) {
- if (next.IsThisOption(compoundArg))
- return true;
- next = next.NextAlternate;
- }
- return false;
- }
- public OptionProcessingResult ProcessArgument(string arg, string nextArg)
- {
- if (IsAlternate(arg + ":" + nextArg))
- return OptionProcessingResult.NotThisOption;
-
- if (IsThisOption(arg))
- {
- if (!NeedsParameter)
- {
- if (VBCStyleBoolean && arg.EndsWith("-"))
- DoIt(false);
- else
- DoIt(true);
- return OptionProcessingResult.OptionAlone;
- }
- else
- {
- DoIt(nextArg);
- return OptionProcessingResult.OptionConsumedParameter;
- }
- }
- if (IsThisOption(arg + ":" + nextArg))
- {
- DoIt(true);
- return OptionProcessingResult.OptionConsumedParameter;
- }
- return OptionProcessingResult.NotThisOption;
- }
- }
- }