Exemplo n.º 1
0
        protected MemberInfoUsage[] GetMembers()
        {
            // Return cached members
            if (members != null)
            {
                return(members);
            }

            // Cache members
            ArrayList memberList = new ArrayList();

            // TODO: Parse base class first to get /v and /h shown first
            BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;

            foreach (MemberInfo info in GetType().GetMembers(flags))
            {
                // Only doing fields and properties
                if ((info.MemberType != MemberTypes.Field) && (info.MemberType != MemberTypes.Property))
                {
                    continue;
                }

                // Skip variables w/o usage
                object[]       attribs = info.GetCustomAttributes(typeof(UsageAttribute), true);
                UsageAttribute usage   = (UsageAttribute)(attribs.Length != 0 ? attribs[0] : null);
                if (usage is NoUsageAttribute)
                {
                    continue;
                }

                // Default settings with no attribute
                if (usage == null)
                {
                    PropertyInfo prop  = info as PropertyInfo;
                    FieldInfo    field = info as FieldInfo;
                    Debug.Assert((prop != null) || (field != null));

                    // If the type is bool, it's probably just a flag
                    if (((prop != null) && (prop.PropertyType == typeof(bool))) ||
                        ((field != null) && (field.FieldType == typeof(bool))))
                    {
                        usage = new FlagUsageAttribute(info.Name);
                    }
                    // If the type is not a bool, it probably also have a value
                    else
                    {
                        usage = new ValueUsageAttribute(info.Name);
                    }
                }

                memberList.Add(new MemberInfoUsage(info, usage));
            }

            members = (MemberInfoUsage[])memberList.ToArray(typeof(MemberInfoUsage));
            return(members);
        }
        protected MemberInfoUsage[] GetMembers()
        {
            // Return cached members
              if( members != null ) return members;

              // Cache members
              ArrayList   memberList = new ArrayList();

              // TODO: Parse base class first to get /v and /h shown first
              BindingFlags    flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
              foreach( MemberInfo info in GetType().GetMembers(flags) ) {
            // Only doing fields and properties
            if( (info.MemberType != MemberTypes.Field) && (info.MemberType != MemberTypes.Property) ) continue;

            // Skip variables w/o usage
            object[]        attribs = info.GetCustomAttributes(typeof(UsageAttribute), true);
            UsageAttribute  usage = (UsageAttribute)(attribs.Length != 0 ? attribs[0] : null);
            if( usage is NoUsageAttribute ) continue;

            // Default settings with no attribute
            if( usage == null ) {
              PropertyInfo    prop = info as PropertyInfo;
              FieldInfo       field = info as FieldInfo;
              Debug.Assert((prop != null) || (field != null));

              // If the type is bool, it's probably just a flag
              if( ((prop != null) && (prop.PropertyType == typeof(bool))) ||
            ((field != null) && (field.FieldType == typeof(bool))) ) {
            usage = new FlagUsageAttribute(info.Name);
              }
            // If the type is not a bool, it probably also have a value
              else {
            usage = new ValueUsageAttribute(info.Name);
              }
            }

            memberList.Add(new MemberInfoUsage(info, usage));
              }

              members = (MemberInfoUsage[])memberList.ToArray(typeof(MemberInfoUsage));
              return members;
        }
Exemplo n.º 3
0
        void Parse(string[] args, bool ignoreFirstArg)
        {
            object[]             attribs = GetType().GetCustomAttributes(typeof(ParserUsageAttribute), true);
            ParserUsageAttribute parser  = (ParserUsageAttribute)(attribs.Length != 0 ? attribs[0] : null);
            bool allowArgFile            = (parser != null ? parser.AllowArgumentFile : true);

            MemberInfoUsage[] members = GetMembers();

            for (int i = (ignoreFirstArg ? 1 : 0); i != args.Length; ++i)
            {
                string arg = args[i];
                Debug.WriteLine("Processing arg: " + arg);

                MemberInfoUsage member = null;
                bool            isFlag = false;

                // It's a flag
                if ((arg.Length > 1) && ((arg[0] == '/') || (arg[0] == '-')))
                {
                    bool   hasOnOff;
                    string flagName;


                    // Flags can have a '+' or '-' suffix. If this arg has a prefix remove it,
                    // else just remove the '/' or '-'
                    hasOnOff = arg.EndsWith("-") || arg.EndsWith("+");
                    if (hasOnOff)
                    {
                        flagName = arg.Substring(1, arg.Length - 2);
                    }
                    else
                    {
                        flagName = arg.Substring(1);
                    }


                    // Flags can be passed in one of two ways
                    //  a) With a param name in 1 arg and a value in the next. e.g. "/flag myValue"
                    //  b) Using a delimiter, passed as a single argument. e.g. "/flag:myValue"
                    // If using the single arg (a) method extract the arg name
                    int delimiterPos = FindValueInlineDeliminter(flagName);


                    //default delimiter. A space which is not a delimiter (space delimted values are split into seperate args)
                    // will thus have a delimiter value of '\0'
                    char delimiter = '\0';
                    if (delimiterPos != -1)
                    {
                        delimiter = flagName[delimiterPos];
                        flagName  = flagName.Substring(0, delimiterPos);
                    }

                    // Find the argument by name
                    member = FindFlag(flagName);

                    if (member != null)
                    {
                        isFlag = true;


                        //OnOff toggle only allowed if: member.usage is FlagUsage and FlagUsage.AllowOnOff is true
                        if (hasOnOff)
                        {
                            FlagUsageAttribute flag = member.usage as FlagUsageAttribute;

                            if (null == flag)
                            {
                                throw new UsageException(arg, "Only flags support on/off toggles");
                            }
                            else if (!flag.AllowOnOff)
                            {
                                throw new UsageException(arg, "Flag does not allow on/off toggle");
                            }
                        }


                        //Check that only value args have a delimiter and that the correct delimiter has been used
                        if (member.usage is ValueUsageAttribute)
                        {
                            ValueUsageAttribute val = (ValueUsageAttribute)member.usage;

                            switch (delimiter)
                            {
                            case ':':  if (0 == (val.Delimiters & ValueDelimiters.Colon))
                                {
                                    throw new UsageException(arg, "This value param does not support a ':' delimiter");
                                }
                                break;

                            case '=':  if (0 == (val.Delimiters & ValueDelimiters.Equals))
                                {
                                    throw new UsageException(arg, "This value param does not support a '=' delimiter");
                                }
                                break;

                            case '\0': if (0 == (val.Delimiters & ValueDelimiters.Space))
                                {
                                    throw new UsageException(arg, "This value param does not support a ' ' delimiter");
                                }
                                break;

                            default: throw new UsageException(arg, "Unknown delimiter");
                            }
                        }
                        else if ('\0' != delimiter)
                        {
                            throw new UsageException(arg, "Only value params support delimiters");
                        }
                    }
                }
                // It's a file name to process parameters from
                else if ((arg.Length > 1) && (arg[0] == '@') && allowArgFile)
                {
                    ParseFromFile(arg.Substring(1));
                    continue;
                }
                // It's a parameter
                else
                {
                    // Find the argument by offset
                    member = GetNextParam();
                }

                if (member == null)
                {
                    throw new UsageException(arg, "Unrecognized argument");
                }

                // Argument with a value, e.g. /foo bar
                if (member.usage.ExpectsValue)
                {
                    string value;


                    // If the arg has an inline delimiter (e.g. "/flag:myValue")
                    // then read the value from the current arg else get the value from the next arg
                    int delimiterPos = FindValueInlineDeliminter(arg);
                    if (delimiterPos == -1)
                    {
                        if (isFlag && (++i == args.Length))
                        {
                            throw new UsageException(arg, "Argument expects a parameter");
                        }
                        value = args[i];
                    }
                    else
                    {
                        if ((arg.Length - 1) == delimiterPos)
                        {
                            throw new UsageException(arg, "Argument expects a paramter");
                        }
                        value = arg.Substring(delimiterPos + 1);
                    }

                    member.usage.ConsumeValue(value, this, member.info);
                }
                // Argument w/o a value, e.g. /foo
                else
                {
                    string value;

                    if (isFlag && arg.EndsWith("-"))
                    {
                        value = "false";
                    }
                    else
                    {
                        value = "true";
                    }

                    member.usage.ConsumeValue(value, this, member.info);
                }
            }

            // Check for missing required arguments
            foreach (MemberInfoUsage member in members)
            {
                if (!member.usage.Optional && !member.usage.IsFound)
                {
                    throw new UsageException(member.info.Name, "Required argument not found");
                }
            }
        }